17 Configuring and Using WLDF Programmatically

This chapter describes how to enable, configure, and monitor the WebLogic Diagnostics Framework (WLDF) programmatically, using the JMX API and the WebLogic Scripting Tool (WLST), as an alternative to performing these tasks using the WebLogic Server Administration Console

This chapter includes the following sections:

In addition to the information provided in those sections, use the information in the following manuals to develop and deploy applications, and to use WLST:

How WLDF Generates and Retrieves Data

In general, diagnostic data is generated and retrieved by WLDF components following this process:

  • The WLDF XML descriptor file settings for the Harvester, Instrumentation, Image Capture, and Watch and Notification components determine the type and amount of diagnostic data generated while a server is running.

  • The diagnostic context and instrumentation settings filter and monitor this data as it flows through the system. Data is harvested, actions are triggered, events are generated, and configured notifications are sent.

  • The Archive component stores the data.

  • The Accessor component retrieves the data.

Configuration is primarily an administrative task, accomplished either through the Administration Console or through WLST scripts. Deployable descriptor modules, XML configuration files, are the primary method for configuring diagnostic resources at both the system level (servers and clusters) and at the application level. (For information about configuring WLDF resources, see Chapter 5, "Understanding WLDF Configuration.")

Output retrieval via the Accessor component can be either an administrative or a programmatic task.

Mapping WLDF Components to Beans and Packages

When you create WLDF resources using the Administration Console or WLST, WebLogic Server creates MBeans (managed beans=) for each resource. You can then access these MBeans using JMX or WLST. Because WLST is a JMX client; any task you can perform using WLST you can also perform programmatically through JMX.

Table 17-1 lists the beans and packages associated with WLDF and its components. Figure 17-1 groups the beans by type.

Figure 17-1 WLDF Configuration MBeans, Run-Time MBeans, and System Module Beans

Description of Figure 17-1 follows
Description of "Figure 17-1 WLDF Configuration MBeans, Run-Time MBeans, and System Module Beans"

Programming Tools

The WebLogic Diagnostics Framework enables you to perform the following tasks programmatically:

  • Create and modify diagnostic descriptor files to configure the WLDF Harvester, Instrumentation, and Watch and Notification components at the server level.

  • Use JMX to access WLDF operations and attributes.

  • Use JMX to create custom MBeans that contain harvestable data. You can then configure the Harvester to collect that data and configure a watches and notifications to monitor the values.

  • Write Java programs that perform the following tasks:

    • Capture notifications using JMX listeners.

    • Capture notifications using JMS.

    • Retrieve archived data through the Accessor. (The Accessor, as are the other components, is surfaced as JMX; you can use WLST or straight JMX programming to retrieve diagnostic data.)

Configuration and Run-Time APIs

The configuration and run-time APIs configure and monitor WLDF. Both the configuration and run-time APIs are exposed as MBeans.

  • The configuration MBeans and system module Beans create and configure WLDF resources, and determine their run-time behavior.

  • The run-time MBeans monitor the run-time state and the operations defined for the different components.

You can use the APIs to configure, activate, and deactivate data collection; to configure watches, notifications, alarms, and diagnostic image captures; and to access data.

Configuration APIs

The Configuration APIs define interfaces that are used to configure the following WLDF components:

  • Data Collectors: You can use the configuration APIs to configure and control Instrumentation, Harvesting, and Image Capture.

    • For the Instrumentation component, you can enable, disable, create, and destroy server-level instrumentation and instrumentation monitors.

      Note:

      The configuration APIs do not support configuration of application-level instrumentation. However, configuration changes for application-level instrumentation can be effected using Java Specification Request (JSR) 88 APIs.
    • For the Harvester component, you can add and remove types to be harvested, specify which attributes and instances of those types are to be harvested, and set the sample period for the harvester.

    • For the Diagnostic Image Capture component, you can set the name and path of the directory in which the image capture is to be stored and the events image capture interval, that is, the time interval during which recently archived events are captured in the diagnostic image.

  • Watch and Notifications: You can use the configuration APIs to enable, disable, create, and destroy watches and notifications. You can also use the configuration APIs to:

    • Set the rule type, watch-rule expressions, and severity for watches

    • Set alarm type and alarm reset period for notifications

    • Configure a watch to trigger a diagnostic image capture

    • Add and remove notifications from watches

  • Archive: Set the archive type and the archive directory

Run-Time APIs

The run-time APIs define interfaces that are used to monitor the run-time state of the WLDF components. Instances of these APIs are instantiated on instances of individually managed servers. These APIs are defined as run-time MBeans, so JMX clients can easily access them.

The run-time APIs encapsulate all other run-time interfaces for the individual WLDF components. These APIs are included in the weblogic.management.runtime package.

You can use the run-time APIs to monitor the following WLDF components:

  • Data Collectors—You can use the run-time APIs to monitor the Instrumentation, Harvester, and the Image Capture components.

    • For the Instrumentation component, you can monitor joinpoint count statistics, the number of classes inspected for instrumentation monitors, the number of classes modified, and the time it takes to inspect a class for instrumentation monitors.

    • For the Harvester component, you can query the set of harvestable types, harvestable attributes, and harvestable instances (that is, the instances that are currently harvestable for specific types). And, you can also query which types, attributes, and instances are currently configured for harvesting. The sampling interval and various run-time statistics pertaining to the harvesting process are also available.

    • For the Image Capture component, you can specify the destination and lockout period for diagnostic images and initiate image captures.

  • Watches and Notifications: You can use the run-time APIs to monitor the Watches and Notifications and Archive components.

    • For the Watches and Notifications component, you can reset watch alarms and monitor statistics about watch-rule evaluations and watches triggered, including information about the analysis of alarms, events, log records, and harvested metrics.

  • Archive: You can monitor information about the archive, such as file name and archive statistics.

  • Data Accessor—You can use the run-time APIs to retrieve the diagnostic data persisted in the different archives. The run-time APIs also support data filtering by allowing you to specify a query expression to search the data from the underlying archive. You can monitor information about column type maps (a map relating column names to the corresponding type names for the diagnostic data), statistics about data record counts and timestamps, and cursors (cursors are used by clients to fetch data records).

WLDF Packages

The following two packages are provided:

  • weblogic.diagnostics.context contains:

    • DiagnosticContextConstants, which defines the indices of dye flags supported by the WebLogic diagnostics system.

    • DiagnosticContextHelper, which provides applications limited access to the diagnostic context.

  • weblogic.diagnostics.watch contains:

    • JMXWatchNotification, an extended JMX notification object which includes additional information about the notification. This information is contained in the referenced WatchNotification object returned from method getExtendedInfo.

    • WatchNotification, which defines a notification for a watch rule.

Programming WLDF: Examples

The examples described in the following sections use WLDF beans and packages to access and modify information about a running server:

In addition, see the WLST and JMX examples in Appendix D, "WebLogic Scripting Tool Examples."

Example: DiagnosticContextExample.java

The following example uses the DiagnosticContextHelper class from the weblogic.diagnostics.context package to get and set the value of the DYE_0 flag. (For information about diagnostic contexts, see Chapter 13, "Configuring the DyeInjection Monitor to Manage Diagnostic Contexts.")

To compile and run the program:

  1. Copy the DiagnosticContextExample.java example (Example 17-1) to a directory and compile it with:

    javac -d . DiagnosticContextExample.java
    

    This will create the ./weblogic/diagnostics/examples directory and populate it with DiagnosticContextExample.class.

  2. Run the program. The command syntax is:

    java weblogic.diagnostics.examples.DiagnosticContextExample
    

    Sample output is similar to:

    # java weblogic.diagnostics.examples.DiagnosticContextExample
    ContextId=5b7898f93bf010ce:40305614:1048582efd4:-8000-0000000000000001
    isDyedWith(DYE_0)=false
    isDyedWith(DYE_0)=true
    

Example 17-1 Example: DiagnosticContextExample.java

package weblogic.diagnostics.examples;
import weblogic.diagnostics.context.DiagnosticContextHelper;
public class DiagnosticContextExample {  
  public static void main(String args[]) throws Exception {
    System.out.println("ContextId=" +
        DiagnosticContextHelper.getContextId());
    System.out.println("isDyedWith(DYE_0)=" + 
       DiagnosticContextHelper.isDyedWith(DiagnosticContextHelper.DYE_0));
    DiagnosticContextHelper.setDye(DiagnosticContextHelper.DYE_0, true);
    System.out.println("isDyedWith(DYE_0)=" + 
         DiagnosticContextHelper.isDyedWith(DiagnosticContextHelper.DYE_0));
  }
}

Example: HarvesterMonitor.java

The HarvesterMonitor program uses the Harvester JMX notification to identify when a harvest cycle has occurred. It then retrieves the new values using the Accessor. All access is performed through JMX. A description of notification listeners and the HarvesterMonitor.java code are provided in the following sections:

For information about the Harvester component, see Chapter 8, "Configuring the Harvester for Metric Collection."

Notification Listeners

Notification listeners provide an appropriate implementation for a particular transport medium. For example, SMTP notification listeners provide the mechanism to establish an SMTP connection with a mail server and trigger an e-mail with the notification instance that it receives. JMX, SNMP, JMS and other types of listeners provide their respective implementations as well.

Note:

You can develop plug-ins that propagate events generated by the WebLogic Diagnostics Framework using transport mediums other than SMTP, JMX, SNMP, or JMS. One approach is to use the JMX NotificationListener interface to implement an object, and then propagate the notification according to the requirements of the selected transport medium.

Table 17-2 describes each notification listener type that is provided with WebLogic Server and the relevant configuration settings for each type.

Table 17-2 Notification Listener Types

Notification Medium Description Configuration Parameter Requirements

JMS

Propagated via JMS Message queues or topics.

Required: Destination JNDI name.

Optional: Connection factory JNDI name (use the default JMS connection factory if not present).

JMX

Propagated via standard JMX notifications.

None required. Uses predefined singleton for posting the event.

SMTP

Propagated via regular e-mail.

Required: MailSession JNDI name and Destination e-mail.

Optional: Subject and body (if not specified, use default)

SNMP

Propagated via SNMP traps and the WebLogic Server SNMP Agent.

None required, but the SNMPTrapDestination MBean must be defined in the WebLogic SNMP agent.


By default, all notifications fired from watch rules are stored in the server log file in addition to being fired through the configured medium.

HarvesterMonitor.java

To compile and run the HarvesterMonitor program:

  1. Copy the HarvesterMonitor.java example (Example 17-2) to a directory and compile it with:

    javac -d . HarvesterMonitor.java
    

    This will create the ./weblogic/diagnostics/examples directory and populate it with HarvesterMonitor.class and HarvesterMonitor$HarvestCycleHandler.class.

  2. Start the monitor. The command syntax is:

    java HarvesterMonitor <server> <port> <uname> <pw> [<types>]
    

    You will need access to a WebLogic Server instance, and will need to know the server's name, port number, administrator's login name, and the administrator's password.

    You can provide an optional list of harvested type names. If provided, the program will display only the values for those types. However, for each selected type, the monitor displays the complete set of collected values; there is no way to constrain the values that are displayed for a selected type.

    Only values that are explicitly configured for harvesting are displayed. Values collected solely to support watch rules (implicit values) are not displayed.

    The following command requires that '.' is in the CLASSPATH variable, and that you run the command from the directory where you compiled the program. The command connects to the myserver server, at port 7001, as user weblogic (and also the password, shown as password):

    java weblogic.diagnostics.examples.HarvesterMonitor myserver 7001
      weblogic password
    

    See Example 17-3 for an example of output from the HarvesterMonitor.

Example 17-2 Example: HarvesterMonitor.java

package weblogic.diagnostics.examples;
import weblogic.management.mbeanservers.runtime.RuntimeServiceMBean;
import javax.management.*;
import javax.management.remote.*;
import javax.naming.Context;
import java.util.*;
public class HarvesterMonitor {

  private static String accessorRuntimeMBeanName;
   private static ObjectName accessorRuntimeMBeanObjectName;
  private static String harvRuntimeMBeanName;
   private static ObjectName harvRuntimeMBeanObjectName;
  private static MBeanServerConnection rmbs;
  private static ObjectName getObjectName(String objectNameStr) {
     try { return new ObjectName(getCanonicalName(objectNameStr)); }
     catch (RuntimeException x) { throw x; }
     catch (Exception x) { x.printStackTrace(); throw new
                                RuntimeException(x); }
  }
  private static String getCanonicalName(String objectNameStr) {
     try { return new ObjectName(objectNameStr).getCanonicalName(); }
     catch (RuntimeException x) { throw x; }
     catch (Exception x) { x.printStackTrace(); throw new
                                 RuntimeException(x); }
  }
  private static String serverName;
   private static int port;
   private static String userName;
   private static String password;
  private static ArrayList typesToMonitor = null;
  public static void main(String[] args) throws Exception {
    if (args.length < 4) {
        System.out.println(
             "Usage: java weblogic.diagnostics.harvester.HarvesterMonitor " +
             "<serverName> <port> <userName> <password> [<types>]" +
              weblogic.utils.PlatformConstants.EOL +
              "   where <types> (optional) is a comma-separated list " +
              "of types to monitor.");
        System.exit(1);
    }
    serverName = args[0];
     port = Integer.parseInt(args[1]);
     userName = args[2];
     password = args[3];
    accessorRuntimeMBeanName = getCanonicalName(
         "com.bea:ServerRuntime=" + serverName +
          ",Name=HarvestedDataArchive,Type=WLDFDataAccessRuntime" +
          ",WLDFAccessRuntime=Accessor,WLDFRuntime=WLDFRuntime");
    accessorRuntimeMBeanObjectName = 
          getObjectName(accessorRuntimeMBeanName);
    harvRuntimeMBeanName = getCanonicalName(
        "com.bea:ServerRuntime=" + serverName +
        ",Name=WLDFHarvesterRuntime,Type=WLDFHarvesterRuntime" +
        ",WLDFRuntime=WLDFRuntime");
    harvRuntimeMBeanObjectName = getObjectName(harvRuntimeMBeanName);
    if (args.length > 4) {
      String typesStr = args[4];
      typesToMonitor = new ArrayList();
      int index;
      while ((index = typesStr.indexOf(",")) > 0) {
        String typeName = typesStr.substring(0,index).trim();
        typesToMonitor.add(typeName);
        typesStr = typesStr.substring(index+1);
      }
      typesToMonitor.add(typesStr.trim());
    }
    rmbs = getRuntimeMBeanServerConnection();
    new HarvesterMonitor().new HarvestCycleHandler();
    while(true) {Thread.sleep(100000);}
  }
  static protected String JNDI = "/jndi/";
  static public MBeanServerConnection getRuntimeMBeanServerConnection()
      throws Exception {
    JMXServiceURL serviceURL;
    serviceURL =
        new JMXServiceURL("t3",
        "localhost",
        port,
        JNDI + RuntimeServiceMBean.MBEANSERVER_JNDI_NAME);
    System.out.println("ServerName=" + serverName);
    System.out.println("URL=" + serviceURL);
    Hashtable h = new Hashtable();
    h.put(Context.SECURITY_PRINCIPAL, userName);
    h.put(Context.SECURITY_CREDENTIALS, password);
    h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
          "weblogic.management.remote");
    JMXConnector connector = JMXConnectorFactory.connect(serviceURL,h);
    return connector.getMBeanServerConnection();
  }
  class HarvestCycleHandler implements NotificationListener {
    // used to track harvest cycles
    private int timestampIndex;
    private int domainIndex;
    private int serverIndex;
    private int typeIndex;
    private int instNameIndex;
    private int attrNameIndex;
    private int attrTypeIndex;
    private int attrValueIndex;  
    long lastSampleTime = System.currentTimeMillis();
    HarvestCycleHandler() throws Exception{
      System.out.println("Harvester monitor started...");
      try {
        setUpRecordIndices();
        rmbs.addNotificationListener(harvRuntimeMBeanObjectName, 
                                     this, null, null);
      }
      catch (javax.management.InstanceNotFoundException x) {
        System.out.println("Cannot find JMX data. " +
                           "Is the server name correct?");
        System.exit(1);
      }
    }
    private void setUpRecordIndices() throws Exception {
      Map columnIndexMap = (Map)rmbs.getAttribute(
          accessorRuntimeMBeanObjectName, "ColumnIndexMap");
      timestampIndex =              ((Integer)columnIndexMap.get("TIMESTAMP")).intValue();
      domainIndex = 
            ((Integer)columnIndexMap.get("DOMAIN")).intValue();
      serverIndex = 
            ((Integer)columnIndexMap.get("SERVER")).intValue();
      typeIndex = 
            ((Integer)columnIndexMap.get("TYPE")).intValue();
      instNameIndex = 
            ((Integer)columnIndexMap.get("NAME")).intValue();
      attrNameIndex = 
            ((Integer)columnIndexMap.get("ATTRNAME")).intValue();
      attrTypeIndex = 
            ((Integer)columnIndexMap.get("ATTRTYPE")).intValue();
      attrValueIndex =              ((Integer)columnIndexMap.get("ATTRVALUE")).intValue();
    }
    public synchronized void handleNotification(Notification notification,
                                                Object handback) {
        System.out.println("\n------------------------------------------");
      long thisSampleTime = System.currentTimeMillis()+1;
      try {
        String lastTypeName = null;
        String lastInstName = null;
        String cursor = (String)rmbs.invoke(accessorRuntimeMBeanObjectName,
                        "openCursor",
                        new Object[]{new Long(lastSampleTime),
                        new Long(thisSampleTime), null},
                        new String[]{ "java.lang.Long",
                        "java.lang.Long", "java.lang.String" } );
        while (((Boolean)rmbs.invoke(accessorRuntimeMBeanObjectName,
                        "hasMoreData",
                        new Object[]{cursor},
                        new String[]{"java.lang.String"})).booleanValue()) {
          Object[] os = (Object[])rmbs.invoke(accessorRuntimeMBeanObjectName,
                        "fetch",
                        new Object[]{cursor},
                        new String[]{"java.lang.String"});
          for (int i = 0; i < os.length; i++) {
            Object[] values = (Object[])os[i];
            String typeName = (String)values[typeIndex];
            String instName = (String)values[instNameIndex];
            String attrName = (String)values[attrNameIndex];
            if (!typeName.equals(lastTypeName)) {
              if (typesToMonitor != null &&
                  !typesToMonitor.contains(typeName)) continue;
              System.out.println("\nType " + typeName);
              lastTypeName = typeName;
            }
            if (!instName.equals(lastInstName)) {
              System.out.println("\n  Instance " + instName);
              lastInstName = instName;
            }
            Object attrValue = values[attrValueIndex];
            System.out.println("    - " + attrName + "=" + attrValue);
          }
        }
        lastSampleTime = thisSampleTime;
      }
      catch (Exception e) {e.printStackTrace();}
    }
  }
}

Example 17-3 contains sample output from the HarvesterMonitor program:

Example 17-3 Sample Output from HarvesterMonitor

ServerName=myserver
URL=service:jmx:t3://localhost:7001/jndi/weblogic.management.mbeanservers.runtime
Harvester monitor started...
------------------------------------------------------
Type weblogic.management.runtime.WLDFHarvesterRuntimeMBean
Instance com.bea:Name=WLDFHarvesterRuntime,ServerRuntime=myserver,Type=WLDFHarvesterRuntime,WLDFRuntime=WLDFRuntime
    - TotalSamplingTime=202048863
    - CurrentSnapshotElapsedTime=1839619
Type weblogic.management.runtime.ServerRuntimeMBean
  Instance com.bea:Name=myserver,Type=ServerRuntime
    - RestartRequired=false
    - ListenPortEnabled=true
    - ActivationTime=1118319317071
    - ServerStartupTime=40671
    - ServerClasspath= [deleted long classpath listing]
    - CurrentMachine=
    - SocketsOpenedTotalCount=1
    - State=RUNNING
    - RestartsTotalCount=0
    - AdminServer=true
    - AdminServerListenPort=7001
    - ClusterMaster=false
    - StateVal=2
    - CurrentDirectory=C:\testdomain\.
    - AdminServerHost=10.40.8.123
    - OpenSocketsCurrentCount=1
    - ShuttingDown=false
    - SSLListenPortEnabled=false
    - AdministrationPortEnabled=false
    - AdminServerListenPortSecure=false
    - Registered=true

Example: JMXAccessorExample.java

The following example program uses JMX to print log entries to standard out. All access is performed through JMX. (For information about the Accessor component, see Chapter 14, "Accessing Diagnostic Data With the Data Accessor.")

To compile and run the program:

  1. Copy the JMXAccessorExample.java example (Example 17-4) to a directory and compile it with:

    javac -d . JMXAccessorExample.java
    

    This will create the ./weblogic/diagnostics/examples directory and populate it with JMXAccessorExample.class.

  2. Start the program. The command syntax is:

    java weblogic.diagnostics.example.JMXAccessor <logicalName> <query>
    

    You will need access to a WebLogic Server instance, and will need to know the server's name, port number, administrator's login name, and the administrator's password.

    The logicalName is the name of the log. Valid names are: HarvestedDataArchive, EventsDataArchive, ServerLog, DomainLog, HTTPAccessLog, ServletAccessorHelper.WEBAPP_LOG, RAUtil.CONNECTOR_LOG, JMSMessageLog, and CUSTOM.

    The query is constructed using the syntax described in Appendix A, "WLDF Query Language." For the JMXAccessorExample program, an empty query (an empty pair of double quotation marks, "") returns all entries in the log.

    The following command requires that '.' is in the CLASSPATH variable, and that you run the command from the directory where you compiled the program. The program uses the IIOP (Internet Inter-ORB Protocol) protocol to connect to port 7001, as user weblogic, with a password shown as password, and prints all entries in the ServerLog to standard out:

    java weblogic.diagnostics.examples.JMXAccessorExample ServerLog ""
    

    You can modify the example to use a username/password combination for your site.

Example 17-4 JMXAccessorExample.java

package weblogic.diagnostics.examples;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Hashtable;
import java.util.Iterator;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;
public class JMXAccessorExample {
  private static final String JNDI = "/jndi/";
  public static void main(String[] args) {
    try {
      if (args.length != 2) {
        System.err.println("Incorrect invocation. Correct usage is:\n" +
          "java weblogic.diagnostics.examples.JMXAccessorExample " +
          "<logicalName> <query>");
        System.exit(1);
      }
      String logicalName = args[0];
      String query = args[1];      
      MBeanServerConnection mbeanServerConnection =
        lookupMBeanServerConnection();
      ObjectName service = new
          ObjectName(weblogic.management.mbeanservers.runtime.RuntimeServiceMBean.OBJECT_NAME);
      ObjectName serverRuntime =
        (ObjectName) mbeanServerConnection.getAttribute(service,
         "ServerRuntime");
      ObjectName wldfRuntime =
        (ObjectName) mbeanServerConnection.getAttribute(serverRuntime,
         "WLDFRuntime");
      ObjectName wldfAccessRuntime =
        (ObjectName) mbeanServerConnection.getAttribute(wldfRuntime,
         "WLDFAccessRuntime");
      ObjectName wldfDataAccessRuntime =
        (ObjectName) mbeanServerConnection.invoke(wldfAccessRuntime,
         "lookupWLDFDataAccessRuntime", new Object[] {logicalName}, 
          new String[] {"java.lang.String"});
      String cursor =
         (String) mbeanServerConnection.invoke(wldfDataAccessRuntime,
          "openCursor", new Object[] {query}, 
          new String[] {"java.lang.String"});
      int fetchedCount = 0;
      do {
        Object[] rows =
         (Object[]) mbeanServerConnection.invoke(wldfDataAccessRuntime,
          "fetch", new Object[] {cursor}, 
          new String[] {"java.lang.String"});
        fetchedCount = rows.length;
        for (int i=0; i<rows.length; i++) {
         StringBuffer sb = new StringBuffer();
          Object[] cols = (Object[]) rows[i];
          for (int j=0; j<cols.length; j++) {
            sb.append("Index " + j + "=" + cols[j].toString() + " ");
          }
          System.out.println("Found row = " + sb.toString());
        }
      } while (fetchedCount > 0);
      mbeanServerConnection.invoke(wldfDataAccessRuntime,
          "closeCursor", new Object[] {cursor},
          new String[] {"java.lang.String"});
      } catch(Throwable th) {
      th.printStackTrace();
      System.exit(1);
    }
  }
   private static MBeanServerConnection lookupMBeanServerConnection ()
          throws Exception {
    // construct JMX service URL
    JMXServiceURL serviceURL;
    serviceURL = new JMXServiceURL("iiop", "localhost", 7001, 
        JNDI + "weblogic.management.mbeanservers.runtime");
    // Specify the user, password, and WebLogic provider package
    Hashtable h = new Hashtable();
    h.put(Context.SECURITY_PRINCIPAL,"weblogic");
    h.put(Context.SECURITY_CREDENTIALS,"password");
    h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
          "weblogic.management.remote");
    // Get jmx connector 
    JMXConnector connector = JMXConnectorFactory.connect(serviceURL,h);
    // return MBean server connection class
    return connector.getMBeanServerConnection();
  } // End - lookupMBeanServerConnection
}