+

Search Tips   |   Advanced Search

Develop an admin client program


This page describes how to develop an admin client program that utilizes WAS administrative APIs and Java Management Extensions (JMX).

Product admin APIs provide control of the operational aspects of the distributed system as well as the ability to update the configuration. For information about the AdminClient interface, view the APIs documentation.

This page also demonstrates examples of MBean operations. For information on MBean programming, see MBean Java API documentation. In this information center, click Reference > Mbean interfaces.

 

  1. Create an AdminClient instance.

    An admin client program needs to invoke methods on the AdminService object that is running in the dmgr or the appserver in the base installation.

    The AdminClient class provides a proxy to the remote AdminService object through one of the supported Java Management Extensions (JMX) connectors.

    • The following example shows how to create an AdminClient instance for the SOAP connector:

      Properties connectProps = new Properties();
       connectProps.setProperty( AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
       connectProps.setProperty(AdminClient.CONNECTOR_HOST, "localhost");
       connectProps.setProperty(AdminClient.CONNECTOR_PORT, "8879");
       connectProps.setProperty(AdminClient.USERNAME, "test2");
       connectProps.setProperty(AdminClient.PASSWORD, "user24test");
       AdminClient adminClient = null;
       try
      {
             adminClient = AdminClientFactory.createAdminClient(connectProps);
      } catch (ConnectorException e)
      {
             System.out.println("Exception creating admin client: " + e);
      }
      

      1. Set up a Properties object.

        The example sets up a Properties object with the properties that are required to get to the server. In this case, you use the SOAP connector to reach the server; for the connector type, use the value: AdminClient.CONNECTOR_TYPE_SOAP.

      2. For simplicity, run the client program on the same machine as the server; use localhost for the host name.

        To access a remote host instead of a local host, use a network resolvable name for that host.

      3. Set the port number on which the server SOAP connector is listening.

        In a single server installation, the default port number for the application server SOAP connector is 8880. In an ND installation, the default port number for the deployment manager SOAP connector is 8879.

      4. After the connection properties are set, use the AdminClientFactory class and the Properties object to create an AdminClient object that is connected to the chosen server.

        Depending on factors such as the desired protocol and security environment, we might need to set other properties. For example, if we enable security for the application client program, include the javax.net.ssl.* properties. For more detailed information about the AdminClient interface, the javax.net.ssl.* properties, and additional creation examples, refer to the AdminClient interface in the APIs documentation.

    • The following example shows how to create an AdminClient instance for the RMI connector. Some commands are split on multiple lines for printing purposes.

      Properties connectProps = new Properties();
       connectProps.setProperty(AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
       connectProps.setProperty(AdminClient.CONNECTOR_HOST, "localhost");
       connectProps.setProperty(AdminClient.CONNECTOR_PORT, "2809");
       connectProps.setProperty(AdminClient.USERNAME, "test2");
       connectProps.setProperty(AdminClient.PASSWORD, "user24test");
       System.setProperty("com.ibm.CORBA.ConfigURL", 
       "file:C:/AA/cf010839.26/profiles/AppSrv02/properties/sas.client.props");
       System.setProperty("com.ibm.SSL.ConfigURL", 
       "file:C:/AA/cf010839.26/profiles/AppSrv02/properties/ssl.client.props");
       AdminClient adminClient = null; 
      try
      {
             adminClient = AdminClientFactory.createAdminClient(connectProps);
      } catch (ConnectorException e)
      {
             System.out.println("Exception creating admin client: " + e);
      }
      

      1. Set up a Properties object.

        The example sets up a Properties object with the properties that are required to get to the server. In this case, you use the Remote Method Invocation connector to reach the server; for the connector type, use the value: AdminClient.CONNECTOR_TYPE_RMI.

      2. For simplicity, run the client program on the same machine as the server; use localhost for the host name.

        To access a remote host instead of a local host, use a network resolvable name for that host.

      3. Set the port number on which the server RMI connector is listening.

        In a single server installation, the default port number for the application server RMI connector is 2809. In an ND installation, the default port number for the dmgr RMI connector is 9809.In a single server installation, the default port number for the appserver SOAP connector is 8880.

      4. After the connection properties are set, use the AdminClientFactory class and the Properties object to create an AdminClient object that is connected to the chosen server.

        Depending on factors such as the desired protocol and security environment, we might need to set other properties. For example, if we enable security for the application client program, we need to set a system property to point to the ssl.client.props file and sas.client.props. If we run on a local machine we can point to the actual location. If we run on a remote machine, we can copy these properties files from the server machine and put them anywhere you want, specifying the path to where you put the files.

        We can specify a user name and password inside sas.client.props, When you do, specify com.ibm.CORBA.loginSource=properties. To set the user name and password inside the client program, specify com.ibm.CORBA.loginSource=none in sas.client.props.

  2. Find an MBean. When you obtain an AdminClient instance, we can use it to access managed resources in the administration servers and appservers. Each managed resource registers an MBean with the AdminService through which we can access the resource. The MBean is represented by an ObjectName instance that identifies the MBean. An ObjectName instance consists of a domain name followed by an unordered set of one or more key properties. The syntax for the domain name follows:

    [domainName]:property=value[,property=value]*
    
    

    For WAS, the domain name is WebSphere and the key properties defined for administration are as follows:


    Table 1. Key property descriptions

    type The type of MBean. For example: Server, TraceService, JVM.
    name The name identifier for the individual instance of the MBean.
    cell The name of the cell that the MBean is running.
    node The name of the node that the MBean is running.
    process The name of the process that the MBean is running.

    Some MBeans in WAS use additional key properties. An MBean without key properties can be registered with the MBean server in a WAS process. However, such an MBean cannot participate in the distributed enhancements that WAS adds, for example, request routing, distributed event notification, and so on. If we know the complete set of key properties for an ObjectName instance, we can use it to find the MBean it identifies. However, finding MBeans without having to know all of their key properties is usually more practical and convenient. Use the wildcard character asterisk (*) for any key properties that you do not need to match.

    The following table provides some examples of object names with wildcard key properties that match single or multiple MBeans.


    Table 2. Examples object names with wildcard key properties

    *:type=Server,* All MBeans of type Server
    *:node=Node1,type=Server,* All MBeans of type Server on Node1
    *:type=JVM,process=server1,node=Node1,* The JVM MBean in the server named server1 node Node1
    *:process=server1,* All MBeans in all servers named server1
    *:process=server1,node=Node1,* All MBeans in the server named server1 on Node1

    We can locate an MBean by querying for it with object names that match key properties.

    The following example shows how to find the MBean for the node agent of node, MyNode:

    String nodeName = "MyNode";
     String query = "WebSphere:type=NodeAgent,node=" + nodeName + ",*";
    ObjectName queryName = new ObjectName(query);
    ObjectName nodeAgent = null;
     Set s = adminClient.queryNames(queryName, null); 
    if (!s.isEmpty())
        nodeAgent = (ObjectName)s.iterator().next();
     else
        System.out.println("Node agent MBean was not found");
    

    1. Build an ObjectName instance with a query string that specifies the key properties of type and node.

      By using a wildcard for the remaining key properties, this pattern matches the object names for all MBeans of the type NodeAgent on the node MyNode. Because only one node agent per node exists, this information is sufficient to identify the MBean that you want.

    2. Give this ObjectName instance to the queryNames method of the AdminClient interface.

      The AdminClient interface performs the remote call to the AdminService interface to obtain the set of MBean object names that match the query. The null second parameter to this method is a query expression (QueryExp) object that we can use as an additional query over the MBeans that match the ObjectName pattern in the first parameter.

    3. Use the set iterator to get the first and, in this case, only element.

      The element is the MBean ObjectName instance of the node agent.

  3. Use the MBean. What a particular MBean can do depends on the management interface of that MBean. An MBean can declare:

    • Attributes that we can obtain or set

    • Operations that we can invoke
    • Notifications for which we can register listeners

    For the MBeans provided by WAS, we can find information about the interfaces they support in the MBean API documentation.

    The following example invokes one of the operations available on the NodeAgent MBean that you located previously.

    The following example starts the MyServer appserver:

    String opName = "launchProcess"; String signature[] = { "java.lang.String" }; String params[] = { "MyServer" }; try
    {
         adminClient.invoke(nodeAgent, opName, params, signature);
    } catch (Exception e)
    {
         System.out.println("Exception invoking launchProcess: " + e);
    }
    
    The AdminClient.invoke method is a generic means of invoking any operation on any MBean. The parameters are:

    • The object name of the target MBean, nodeAgent

    • The name of the operation, opName

    • An object array that contains the operation parameters, params

    • A string array that contains the operation signature, signature

    The launchProcess operation in the example has a single parameter which is a string that identifies the server to start.

    The invoke method returns an object instance, which the calling code can use to cast to the correct return type for the invoked operation. The launchProcess operation is declared void so that we can ignore the return value in this example.

  4. Register for events. In addition to managing resources, the JMX API also supports application monitoring for specific administrative events. Certain events produce notifications, for example, when a server starts. Administrative applications can register as listeners for these notifications. The WAS provides a full implementation of the JMX notification model, and provides additional function so we can receive notifications in a distributed environment.

    For a complete list of the notifications emitted from product MBeans, refer to the com.ibm.websphere.management.NotificationConstants class in the MBean API documentation

    The following example shows how an object can register for event notifications that are emitted from an MBean using the ObjectName node agent:

    adminClient.addNotificationListener(nodeAgent, this, null, null);
    

    In this example, the first parameter is the ObjectName for the node agent MBean. The second parameter identifies the listener object, which must implement the NotificationListener interface. In this case, the calling object is the listener. The third parameter is a filter that we can use to indicate which notifications you want to receive. When you leave this value as null, you receive all notifications from this MBean. The final parameter is a handback object that we can use to set the JMX API to return to you when it emits a notification.

    If wer MBean is located on another server in the cell, we can receive its notifications even though the admin client program might be connected to the deployment manager server. All notifications flow to the upstream server. For example, a notification from an appserver first flows to the local node agent and then to the dmgr.

    Another enhanced feature that Application Server provides is the ability to register as a notification listener of multiple MBeans with one call. This registration is done through the addNotificationListenerExtended method of the AdminClient interface, an extension of the standard JMX addNotificationListener method. This extension method even lets you register for MBeans that are not currently active. This registration is important in situations where you want to monitor events from resources that can be stopped and restarted during the lifetime of the admin client program.

  5. Handle the events. Objects receive JMX event notifications through the handleNotification method, which is defined by the NotificationListener interface and which any event receiver must implement.

    The following example is an implementation of the handleNotification method that reports the notifications that it receives:

    public void handleNotification(Notification n, Object handback)
    {
         System.out.println("***************************************************");
         System.out.println("* Notification received at " + new Date().toString());
         System.out.println("* type      = " + ntfyObj.getType());
         System.out.println("* message   = " + ntfyObj.getMessage());
         System.out.println("* source    = " + ntfyObj.getSource());
         System.out.println(
         "* seqNum    = " + Long.toString(ntfyObj.getSequenceNumber()));
         System.out.println("* timeStamp = " + new Date(ntfyObj.getTimeStamp()));
         System.out.println("* userData  = " + ntfyObj.getUserData());
         System.out.println("***************************************************");
    }
    

 

Example

Copy the contents to a file named AdminClientExample.java. After changing the node name and server name to the appropriate values for the configuration, we can compile and run it using the instructions from Create a custom Java administrative client program using WAS admin Java APIs

import java.util.Date;
 import java.util.Properties;
 import java.util.Set;
 import javax.management.InstanceNotFoundException;
 import javax.management.MalformedObjectNameException;
 import javax.management.Notification;
 import javax.management.NotificationListener;
 import javax.management.ObjectName;
 import com.ibm.websphere.management.AdminClient;
 import com.ibm.websphere.management.AdminClientFactory;
 import com.ibm.websphere.management.exception.ConnectorException;
 public class AdminClientExample implements NotificationListener
{

    private AdminClient adminClient;
    private ObjectName nodeAgent;
    private long ntfyCount = 0;

    public static void main(String[] args)
    {
       AdminClientExample ace = new AdminClientExample();

       
// Create an AdminClient
       ace.createAdminClient();

       
// Find a NodeAgent MBean
       ace.getNodeAgentMBean("ellington");

       
// Invoke launchProcess
       ace.invokeLaunchProcess("server1");

       
// Register for NodeAgent events
       ace.registerNotificationListener();
        
       
// Run until interrupted
       ace.countNotifications();
    }

    private void createAdminClient()
    {
        
// Set up a Properties object for the JMX connector attributes
        Properties connectProps = new Properties();
        connectProps.setProperty(
        AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
        connectProps.setProperty(AdminClient.CONNECTOR_HOST, "localhost");
        connectProps.setProperty(AdminClient.CONNECTOR_PORT, "8879");
        
        
// Get an AdminClient based on the connector properties
        try
        {
            adminClient = AdminClientFactory.createAdminClient(connectProps);
        }
        catch (ConnectorException e)
        {
            System.out.println("Exception creating admin client: " + e);
            System.exit(-1);
        }
        
        System.out.println("Connected to DeploymentManager");
    }
    
    
    private void getNodeAgentMBean(String nodeName)
    {
        
// Query for the ObjectName of the NodeAgent MBean on the given node
        try
        {
            String query = "WebSphere:type=NodeAgent,node=" + nodeName + ",*";
            ObjectName queryName = new ObjectName(query);
            Set s = adminClient.queryNames(queryName, null);
            if (!s.isEmpty())
                nodeAgent = (ObjectName)s.iterator().next();
            else
            {
                System.out.println("Node agent MBean was not found");
                System.exit(-1);
            }
        }
        catch (MalformedObjectNameException e)
        {
            System.out.println(e);
            System.exit(-1);
        }
        catch (ConnectorException e)
        {
            System.out.println(e);
            System.exit(-1);
        }
        
        System.out.println("Found NodeAgent MBean for node " + nodeName);
    }
    
    private void invokeLaunchProcess(String serverName)
    {
        
// Use the launchProcess operation on the NodeAgent MBean to start
        
// the given server
        String opName = "launchProcess";
        String signature[] = { "java.lang.String" };
        String params[] = { serverName };
        boolean launched = false;
        try
        {
            Boolean b = (Boolean)adminClient.invoke(
             nodeAgent, opName, params, signature);
            launched = b.booleanValue();
            if (launched)
                System.out.println(serverName + " was launched");
            else
                System.out.println(serverName + " was not launched");

        }
        catch (Exception e)
        {
            System.out.println("Exception invoking launchProcess: " + e);
        }
    }
    
    private void registerNotificationListener()
    {
        
// Register this object as a listener for notifications from the         
// NodeAgent MBean.  Don't use a filter and don't use a handback
        
// object.
        try
        {
            adminClient.addNotificationListener(nodeAgent, this, null, null);
            System.out.println("Registered for event notifications");
        }
        catch (InstanceNotFoundException e)
        {
            System.out.println(e);
            e.printStackTrace();
        }
        catch (ConnectorException e)
        {
            System.out.println(e);
            e.printStackTrace();
        }
    }
    
    public void handleNotification(Notification ntfyObj, Object handback)
    {
        
// Each notification that the NodeAgent MBean generates will result in
        
// this method being called
        ntfyCount++;
        System.out.println("***************************************************");
        System.out.println("* Notification received at " + new Date().toString());
        System.out.println("* type      = " + ntfyObj.getType());
        System.out.println("* message   = " + ntfyObj.getMessage());
        System.out.println("* source    = " + ntfyObj.getSource());
        System.out.println(
        "* seqNum    = " + Long.toString(ntfyObj.getSequenceNumber()));
        System.out.println("* timeStamp = " + new Date(ntfyObj.getTimeStamp()));
        System.out.println("* userData  = " + ntfyObj.getUserData());
        System.out.println("***************************************************");

    }
    
    private void countNotifications()
    {
        
// Run until killed
        try
        {
            while (true)
            {
                Thread.currentThread().sleep(60000);
                System.out.println(ntfyCount + " notification have been received");
            }
        }
        catch (InterruptedException e)
        {
        }
    }
    
}


Example: Administrative client program

 

Related concepts


Additional Application Programming Interfaces (APIs)

 

Related tasks


Create a custom Java admin client program using WAS admin Java APIs
Use application clients