This topic describes how to develop an administrative client program
that utilizes WebSphere Application Server administrative application programming
interfaces (APIs) and Java Management Extensions (JMX).
About this task
WebSphere Application Server administrative APIs provide control
of the operational aspects of your distributed system as well as the ability
to update your configuration. For information about the AdminClient interface,
view the application programming interfaces documentation.
This topic also
demonstrates examples of MBean operations. For information about MBean programming,
refer to the Reference materials. Select API documentation,
then MBean interfaces.
- Create an AdminClient instance.
An administrative
client program needs to invoke methods on the AdminService object that is
running in the deployment manager or the application server 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 Simple Object Access Protocol (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);
}
- Set up a Properties object.
The example sets up a Properties object
with the properties that are required to get to your server. In this case,
you use the SOAP connector to reach the server; for the connector type, use
the value: AdminClient.CONNECTOR_TYPE_SOAP.
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.
- 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
a Network Deployment installation, the default port number for the deployment
manager SOAP connector is 8879.
- After the connection properties are set, use the AdminClientFactory class
and the Properties object to create an AdminClient object that is connected
to your chosen server.
Depending on factors such as your desired protocol
and security environment, you might need to set other properties. For example,
if you enable security for your 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 application programming interfaces documentation.
- The following example shows how to create an AdminClient instance for
the Remote Method Invocation (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);
}
- Set up a Properties object.
The example sets up a Properties object
with the properties that are required to get to your 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.
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.
- 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 a Network Deployment installation, the default
port number for the deployment manager RMI connector is 9809.In a single server
installation, the default port number for the application server SOAP connector
is 8880.
- After the connection properties are set, use the AdminClientFactory class
and the Properties object to create an AdminClient object that is connected
to your chosen server.
Depending on factors such as your desired protocol
and security environment, you might need to set other properties. For example,
if you enable security for your application client program, you need to set
a system property to point to the ssl.client.props file and the sas.client.props
file. If you run on a local machine you can point to the actual location.
If you run on a remote machine, you can copy these properties files from the
server machine and put them anywhere you want, specifying the path to where
you put the files.
You can specify a user name and password inside the
sas.client.props file, When you do, specify com.ibm.CORBA.loginSource=properties.
If you want to set the user name and password inside your client program,
specify com.ibm.CORBA.loginSource=none in the sas.client.props
file.
- Find an MBean. When you obtain an AdminClient instance,
you can use it to access managed resources in the administration servers and
application servers. Each managed resource registers an MBean with the AdminService
through which you 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 WebSphere Application Server, the domain name
is WebSphere and the key properties defined for administration are
as follows:
type |
The type of MBean. For example: Server,
TraceService, Java virtual machine (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 WebSphere Application Server use additional key
properties. An MBean without key properties can be registered with the MBean
server in a WebSphere Application Server process. However, such an MBean cannot
participate in the distributed enhancements that WebSphere Application Server
adds, for example, request routing, distributed event notification, and so
on.
If you know the complete set of key properties for an ObjectName
instance, you 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.
*: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 |
You 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");
- 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.
- 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 you can use as an additional query
over the MBeans that match the ObjectName pattern in the first parameter.
- 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.
- Use the MBean. What a particular MBean can do depends
on the management interface of that MBean. An MBean can declare:
- Attributes that you can obtain or set
- Operations that you can invoke
- Notifications for which you can register listeners
For the MBeans provided by WebSphere Application Server, you 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 application
server: 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 you can ignore the return value in this example.
- 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 WebSphere Application Server provides a full implementation of the JMX
notification model, and provides additional function so you can receive notifications
in a distributed environment. For a complete list of the notifications
emitted from WebSphere Application Server 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 you 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 you can use to set the JMX API to return to you when it emits
a notification.
If
your MBean is located on another server in the cell, you can receive its notifications
even though your administrative client program might be connected to the deployment
manager server. All notifications flow to the upstream server. For example,
a notification from an application server first flows to the local node agent
and then to the deployment manager.
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 your administrative client program.
- 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 your
configuration, you can compile and run it using the instructions from
Creating a custom Java administrative
client program using WebSphere Application Server administrative Java APIsimport 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)
{
}
}
}