You can develop an administrative client program that utilizes WebSphere® Application Server administrative
application programming interfaces (APIs) and Java Management
Extensions (JMX).
About this task
Product 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.
See
examples of MBean operations. For information on MBean programming,
see MBean Java API documentation. In this information center, click .
This example shows how to get and use
a NodeAgent MBean, which is not available for your product. However,
the description of how to get and put the NodeAgent MBean is similar
to what you would do for other MBeans that are available for your
product.
Procedure
- Create an AdminClient instance.
An administrative client program needs
to invoke methods on the AdminService object that is running in 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.
- 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_RMI);
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);
}
Supported configurations: When you use the createAdminClient
method within application code that runs on an application server,
such as within servlets and JavaServer Pages (JSP) files, you must
set the CACHE_DISABLED property to true. For example:
connectProps.setProperty(AdminClient.CACHE_DISABLED, "true");
sptcfg
- 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 WebSphere Application Server, Network Deployment installation,
the default port number for the deployment manager RMI connector is
9809.
- 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:Table 1. Key property descriptions. Key
properties include types, name, cell, node, and process.Key Property |
Description |
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
the product 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.
Table 2. Examples object names with
wildcard key properties. Include asterisks (*) to specify
wildcard key properties.Object name |
Description |
*: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 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
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.
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("***************************************************");
}
Results
The administrative client can handle event notifications
that are emitted from an MBean.
Avoid trouble: If a client
program registers a notification listener through an RMI or JSR160RMI
connector and the ORB thread does not stop running, and thus prevents
the Java virtual machine from exiting, add a
System.exit() statement
to the client program. The ORB starts a thread to handle notification
propagation to the client. This thread does not automatically exit
with the client main thread unless the main thread has a
System.exit() statement.
Place a
System.exit() statement in a location in
the client program that enables the ORB thread and main thread to
stop processing. For example, place the
System.exit() statement
in a
catch or
finally clause of
the client program main
try block.
gotcha
Example: Administrative client program
This example shows how to connect to
the node agent server, which is not available for your product. However,
you can connect to your server by changing the host and port values.
Substitute your server for the node agent server references. Since
the NodeAgent MBean is not available for your product, substitute
the queryNames string to search for another MBean.
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)
{
}
}
}