Skip Headers

Oracle® Containers for J2EE Developer's Guide 10g Release 3 (10.1.3) Part No. B14433-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# 5 Creating MBeans to Manage Your Applications

This chapter provides guidelines on creating and deploying MBeans that will be used to manage applications that will be deployed into OC4J. It includes the following sections:

- What Are MBeans?

- Packaging Your MBeans for Deployment

- Registering Your MBeans with the OC4J MBeanServer

- Providing Management Access to Application-Defined MBeans

## What Are MBeans?

An MBean, or managed bean, is a Java object that represents a manageable resource in a distributed environment, such as an application, a service, a component or a device. You can create MBeans for deployment with an application into OC4J, enabling the application or its components to be managed and monitored through the Web-based Oracle Enterprise Manager 10g Application Server Control Console user interface.

J2EE-related MBeans are defined in the J2EE Management Specification (JSR-77), which is part of the J2EE 1.4 specification as published by Sun Microsystems. This JSR defines a set of managed objects and associated functionality that must be supported by J2EE-compliant containers. OC4J is fully compliant with JSR-77.

An MBean has a management interface that is exposed to enable a management client to manage the resource. The interface is comprised of:

- Attributes, name/value pairs of any type that the management client can get or set. Attributes are analogous to properties set on a JavaBean.

- Operations, methods with any signature and any return type that the client can invoke.

- Notifications that can be generated when specific events occur.

The actual management functionality is provided by the OC4J MBeanServer, which runs as a service within OC4J. The MBeanServer is able to discover, instantiate and access MBeans supplied with your application, exposing the MBeans to other OC4J components and enabling administrators to manage the application. Methods called on the MBeanServer access MBean attributes and operations and control MBean instances.

All MBeans deployed with an application must be registered with the OC4J MBeanServer. See "Registering Your MBeans with the OC4J MBeanServer" for details.

For more on the J2EE Management Specification (JSR-77), visit the Java Community Process site at the following link:

    http://jcp.org/en/jsr/detail?id=77

### Types of MBeans Supported by OC4J

Any of the following MBean types defined in JMX can be deployed into OC4J:

- Standard MBeans

  These are the simplest MBeans to design and implement; however, they are viable only in a static management interface.

  The attributes and operations of a Standard MBean are derived from a Java interface which includes the suffix `MBean` in its name. A Java object can be a Standard MBean simply by being of a class that has the same name as the interface, but without the `MBean` suffix. For example, an object would be of the class `Manager`, in the same Java package as the interface `ManagerMBean`.

  A Standard MBean can also be created from the `javax.management.StandardMBean` class.

- Dynamic MBeans

  These are MBeans that expose a dynamic management interface that is implemented at runtime. Metadata describing each exposed attribute and operation must be made available to the calling application, essentially providing a self-documenting interface.

  Dynamic MBeans must implement the `javax.management.DynamicMBean` interface.

- Model MBeans

  These are Dynamic MBeans that can be configured at runtime. The runtime administration of OC4J is implemented using MBeans of this type.

  A Model MBean implementation can be reused many times with different management interfaces and managed resources, and can provide common functionality such as persistence and caching.

  Model MBeans are defined by the interface `javax.management.modelmbean.ModelMBean`. A Model MBean must be implemented as an object of the `javax.management.modelmbean.RequiredModelMBean` class.

- Open MBeans

  Another type of Dynamic MBean that can be discovered and used by a client at runtime, without requiring the deployment of additional JAR files. Open MBeans are usable with remote management programs that may not have access to application-specific types, including non-Java programs.

  Open MBeans are defined by the package `javax.management.openmbean`.

MBean implementation classes that are registered at deployment time or during application startup— such as MBeans defined in `orion-application.xml`—must include a no-arguments constructor. (See "Registering Your MBeans with the OC4J MBeanServer" for guideline.) If the application creates and registers its MBeans, no such requirement exists.

The `oracle.j2ee.admin.jmx` package provides JMX state management capabilities, including localization support, that you may want to consider implementing in your MBean classes. See "Adding Localization Support to Your MBeans" for details.

## Packaging Your MBeans for Deployment

MBeans are packaged with the application they will manage. Package MBean classes in a JAR file, and add the JAR file to the root level of the application's EAR file structure.

This section includes the following topics:

- Defining MBeans in orion-application.xml

- Initializing MBean Attributes

### Defining MBeans in orion-application.xml

You can provide the configuration data needed to register your MBeans upon deployment by defining them in `orion-application.xml`, the OC4J-specific extension to the J2EE standard `application.xml` descriptor. Both of these descriptors are packaged with the MBeans in the parent application's EAR file.

MBeans defined in `orion-application.xml` will be registered automatically with the OC4J MBeanServer upon deployment or application start. If the application is undeployed, any MBeans belonging to it will also be undeployed.

Add the following XML elements to this descriptor to register the MBeans included in the EAR:

- A `<library>` element pointing to the JAR containing the MBean classes. Set the `path` attribute to the JAR name, as shown below:

      <library path="MyMBeans.jar"/>

- A unique `<jmx-mbean>` element for each MBean class included with the application. Each element registers an MBean class with the MBeanServer.

  The `<jmx-mbean>` element has the following attributes:

  - `objectname`: The name to register the MBean under. The domain part of the name will be ignored even if specified; application MBeans are registered using the application's deployment name as the domain name.

    For example, if you deploy an MBean named`MyMBeanA` with an application named `widget`, supply`:name=MyMBeanA` as the value of this attribute. The name will then be displayed as `widget:name=MyMBeanA`.

    Ideally, the MBean name should include a `type` property indicating the logical MBean type, such as Servlet, Application, DisplayController, etc.

  - `class`: The MBean implementation class.

  The `<jmx-mbean>` element optionally takes the following sub-elements:

  - A `<description>` sub-element containing a readable name. This name will be displayed in the MBean browser user interface.

  - One or more `<attribute>` elements, each defining an initial value to set for an attribute of the MBean. See "Initializing MBean Attributes" for details.

  The following example defines two application-specific MBeans in the `orion-application.xml` deployment descriptor packaged in the parent application's EAR file:

      <orion-application>
        ...
        <jmx-mbean objectname=":type=Application,name=MyMBeanA"
          class="my.mbeans:MBeanTypeA">
          <description>My First MBean</description>
        </jmx-mbean>
        <jmx-mbean objectname=":type=Application,name=MyMBeanB"
          class="my.mbeans:MBeanTypeB">
          <description>My Second MBean</description>
        </jmx-mbean>
      </orion-application>

### Initializing MBean Attributes

You can pre-configure an MBean by setting initial values for one or more of its attributes in the `orion-application.xml` descriptor packaged with the MBean. The MBean attributes will be initialized with these values upon instantiation.

Attribute values must be one of the following types to be preconfigured:

- Primitive types (such as int, long, Integer, and Boolean)

- String constructors (In the current release, this value must be a `javax.management.ObjectName` value representing the object name of an MBean.)

- One-dimensional arrays of these supported types

Each attribute and its value is specified in an `<attribute>` element within the `<jmx-mbean>` element defining the MBean in `orion-application.xml`.

The actual value is specified in a `<value>` subelement. Multiple `<value>` subelements containing string values to set for the same attribute can be wrapped within a `<values>` element.

The following example illustrates how the supported value types can be set within a `<jmx-mbean>` element:

    <orion-application>
      ...
      <jmx-mbean objectname=":type=Application,name=MyMBeanA"
         class="my.mbeans:MBeanTypeA">
        <description>My First MBean</description>
        <attribute name="attr1">
          <value>true</value>
        </attribute>
        <attribute name="attr2">
          <value>100</value>
        </attribute>
        <!-- An array of strings -->
        <attribute name="attr3">
          <value>Test string 1</value>
          <value>Test string 2</value>
          <value>Test string 3</value>
        </attribute>
        <!-- A javax.management.ObjectName representing the name of an MBean -->
        <attribute name="attr3">
         <value>MyApp:Type=Administration</value>
        </attribute>
      </jmx-mbean>
    </orion-application>

## Registering Your MBeans with the OC4J MBeanServer

The MBeans deployed with your application must be registered with the MBeanServer. Once registered, an MBean is fully manageable through the System MBean Browser component of the Application Server Control Console user interface.

You have the following options for registering MBeans:

- Define the MBeans in an `orion-application.xml` descriptor that is packaged with the MBeans in the application EAR file.

  This is the most straightforward mechanism for automatically registering MBeans at the time of deployment. See "Defining MBeans in orion-application.xml" for details

  Note: An MBean can optionally be registered under the global `default` application, which makes it visible to all other applications deployed into the OC4J instance. MBeans are registered with the `default` application by adding a `<jmx-mbean>` element to the OC4J-specific `application.xml` file, located in the `ORACLE_HOME``/home/j2ee/config` directory by default. The formats of `application.xml` and `orion-application.xml` files are defined by the same XML schema. See "Defining MBeans in orion-application.xml" for details on the `<jmx-mbean>` element.

- Define the MBean in the application's deployment plan at deployment time.

  A deployment plan consolidates all of the OC4J-specific configuration data that is spread among multiple deployment descriptors, including `orion-application.xml`. Data set in the deployment plan is persisted to the `orion-application.xml` descriptor created for the application within OC4J.

  Deployment plans can be created or edited at deployment time using the deployment plan editor functionality provide in Application Server Control Console and Oracle JDeveloper 10g. See the Oracle Containers for J2EE Deployment Guide for detailed guidelines on creating and working with deployment plans.

- Programmatically register the MBeans from within the code of an application.

  See the next section, "Programmatically Registering MBeans via Application Code" for implementation guidelines.

### Programmatically Registering MBeans via Application Code

MBeans can optionally be registered dynamically from within the code of an application.

When MBeans are registered programmatically, they are bound to the containing application's lifecycle. This means that if the application is undeployed, all of its MBeans are automatically unregistered from the MBeanServer.

An application that will register MBeans must import the`javax.management` package, which provides the core JMX classes, including classes needed to access the OC4J MBeanServer. The MBean implementation class must also be available to the application.

Applications gain access to the OC4J MBeanServer by creating a reference through the `javax.management.MBeanServerFactory`, as shown in the code snippet below:

    MBeanServer mbsvr = MBeanServerFactory.newMBeanServer();

Note the following restrictions:

- MBeans must be registered under an `ObjectName` whose domain is the namespace under which the application was deployed. This will ensure that beans live in their own namespace within OC4J. The `getDefaultDomain()` method can be called on the `MBeanServer` object to return the correct domain for a given application.

- An application can only set attributes and call methods on MBeans that belong to it. In fact, MBeans that belong to other applications are not visible to the application.

The following code snippet registers an MBean with the OC4J MBeanServer. The MBean is an object of the `oracle.oc4j.admin.jmx.server.mbeans.Tester` class.

    try
      {
        // Get a reference to the MBeanServer
        MBeanServer _mbeanServer = MBeanServerFactory.newMBeanServer();

          // Create the MBean instance
          Tester bean = new Tester();

          //Construct the MBean name using the default application's domain name
          ObjectName beanName= new ObjectName(mbsrv.getDefaultDomain()+
                                              ":type=Tester,name=MyMBean");

        // Register the MBean with the MBeanServer
        mbsrv.registerMBean(bean, beanName);
      }  catch(Exception e)
      {
        // Handle exceptions; for simplicity, dump the stack trace to show any
        // errors that occur
        e.printStackTrace();
      }

The next example is a sample servlet - `UserMBeanServlet` - that will register an MBean with the OC4J MBeanServer in its `init()` method.

    package web;

    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;

    import javax.management.*;

    import oracle.oc4j.admin.jmx.server.mbeans.Tester;

    public class UserMBeanServlet extends HttpServlet {

    public void init() throws ServletException {
      try {
          // Get a reference to the MBeanServer
          MBeanServer mbsrv = MBeanServerFactory.newMBeanServer();

          // Create the MBean instance
          Tester bean = new Tester();

          //Construct the MBean name using the application's domain name
          ObjectName beanName= new ObjectName(mbsrv.getDefaultDomain()+
                                   ":type=Tester,userprop1=bean,userprop2=beanProp2");

        // Register the MBean with the MBeanServer
        mbsrv.registerMBean(bean, beanName);

        // Print a success message to the console
        System.out.println("Finished registering" +beanName);

        }
    catch(Exception e) {
    // Dump the stack trace to show any errors that occur
    e.printStackTrace();
        }
      }
    //Standard servlet code for handling requests
    ...
    }

## Providing Management Access to Application-Defined MBeans

If you provide MBeans with your application, you will likely want to enable users to access and manage the MBeans remotely.

Application MBeans can be managed remotely by accessing the remote OC4J MBeanServer through JSR-160 compliant code. JSR-160 a standard API to connect to remote JMX-enabled applications using RMI. This is also known as JMX remoting.

You have two options for remotely managing MBeans:

- Remote Management Using the Management EJB (JSR-77)

- Remote Management Using the JMX Remote API (JSR-160)

### Prerequisite: Add User to Security Group

To access an application's MBeans, the user must be added to the `oc4j-app-administrators` security groups. Users can be added to groups using either the JAZN Admintool or the Web-based Oracle Enterprise Manager 10g Application Server Control Console.

Note that the `oc4j-app-administrators` security group must have permission to login and invoke methods on the remote OC4J process. The group must also have namespace read access on the server.

See the Oracle Containers for J2EE Security Guide for detailed instructions on adding users to security groups.

### Remote Management Using the Management EJB (JSR-77)

In compliance with the J2EE Management Specification (JSR-77), OC4J allows users to remotely manage MBeans through the Management EJB (MEJB), which is deployed with the OC4J implementation. The MEJB is a stateful session bean that provides a remote interface to the OC4J MBeanServer, allowing remote users to query and access MBeans running in an OC4J instance.

The MEJB uses JMX classes and interfaces. The `javax.management.j2ee.Management` interface is the MEJB remote interface, while the `javax.management.j2ee.ManagementHome` interface contains a single method which creates an MEJB instance. The MEJB is available under the JNDI name `ejb/mgmt/MEJB`.

The following discussions explain how the MEJB can be used:

- Accessing the MEJB from a J2EE Application Client

- Accessing the MEJB from a Servlet or EJB

#### Accessing the MEJB from a J2EE Application Client

The following code enables an application client to use the MEJB. Note that accessing the MEJB from an application client allows both local and remote operations to be performed.

    import javax.naming.*;

    // Import the MEJB interface
    import javax.management.j2ee.Management;
    import javax.management.j2ee.ManagementHome;

    .....

    Hashtable env = new Hashtable();

    // Set the connection target
    String url = "ormi://host.company.com:23791/default";

    // Set the login context
    env.put(Context.PROVIDER_URL, url);
    env.put(Context.SECURITY_PRINCIPAL, "oc4jadmin");
    env.put(Context.SECURITY_CREDENTIALS, "welcome");
    env.put(Context.INITIAL_CONTEXT_FACTORY,
      "com.evermind.server.ApplicationClientInitialContextFactory");

    // Look up the MEJB Home interface and create the MEJB
    Context ctx = new InitialContext(environment);
    Object hm= ctx.lookup("java:comp/env/ejb/mgmt/MEJB");
    ManagementHome mgmtHome=
     (ManagementHome)PortableRemoteObject.narrow(hm,ManagementHome.class);
    Management mejb=  mgmtHome.create();

    .....

    mejb.remove();

#### Accessing the MEJB from a Servlet or EJB

The following code enables a servlet or EJB running within the target OC4J instance to use the MEJB. Because the connection target is the executing container, the login and password data is not supplied, but is instead retrieved from the executing thread context. For this reason, the authenticating user must belong to the `oc4j-administrators` security group.

See the Oracle Containers for J2EE Security Guide for details on adding users to groups.

    import javax.naming.*;

    // Import the JSR-77 MEJB interface
    import javax.management.j2ee.Management;
    import javax.management.j2ee.ManagementHome;

    .....

    // Look up the MEJB Home interface and create the MEJB
    Context ctx= new InitialContext();
    Object hm= ctx.lookup("java:comp/env/ejb/mgmt/MEJB");
    ManagementHome mgmtHome=
     (ManagementHome)PortableRemoteObject.narrow(hm,ManagementHome.class);
    Management mejb=  mgmtHome.create();

    .....

    mejb.remove();

### Remote Management Using the JMX Remote API (JSR-160)

The JMX Remote API (JSR-160) provides another option for managing MBeans remotely. In fact, it offers a number of advantages over using the MEJB defined by JSR-77, making it the preferred method for remote management:

- More of the MBeanServer functionality is available than is exposed through the MEJB.

- Compliant code can easily be migrated to use new connection protocols as they become available.

- The OC4J `JMXConnector` implementation supports localization and HTTP tunneling, which allows clients to communicate with an MBeanServer across firewalls.

  Note that ORMI over SSL, ORMIS, is also supported. See the Oracle Containers for J2EE Security Guide for detailed instructions on adding users to security groups.

- The `JMXConnector` also allows the connection state to be monitored.

Note that because OC4J uses ORMI, and not JRMP, the Oracle JMX Remote API implementation is not compatible with other JSR-160 implementations.

The JMX Remote API defines a standard connector that provides Java clients with remote access to an MBeanServer via the RMI protocol. In the OC4J implementation, the connector is attached to the OC4J MBeanServer. Actual management is through a proxy; for each method called on the proxy instance, a corresponding method is to be called on the remote MBeanServer.

The following discussions explain how the API can be used:

- Connecting to the OC4J MBeanServer

- Connecting to an Application-Specific MBean Server

- Connecting to a Specific Application's JMX Domain

- Setting the JMX Service URI for an OPMN-Managed OC4J Instance

- Setting the JMX Service URI for a Standalone OC4J Instance

- Setting a Locale

- Enabling HTTP Tunneling

#### Connecting to the OC4J MBeanServer

The following sample code creates a `JMXConnector` instance and uses it to connect to a target OC4J instance defined as a `JMXServiceURL` object. An `MBeanServerConnection` instance, which serves as a proxy for the OC4J MBeanServer, is retrieved. The proxy allows management operations to be performed on the MBeanServer operations; in this case, retrieving all the MBeans registered with the MBeanServer.

Note: To connect in the manner outlined in this section, the user must be assigned to the `oc4j-administrators` role, which grants the user full access to the MBeanServer and all of the MBeans registered with it, including OC4J system and application-defined MBeans. The default OC4J administration user, `oc4jadmin`, is a member of this role. See "Connecting to a Specific Application's JMX Domain" for guidelines on enabling a user to access a specific application's MBeans without assigning the user to the `oc4j-administrators` role.

The example code imports the following JMX classes and interfaces:

- `javax.management.remote.JMXConnector` interface

  Defines the client end of the JMX connector.

- `javax.management.remote.JMXConnectorFactory` class

  A factory containing methods to create JMX connector clients.

- `javax.management.remote.JMXServiceURL` class

  Constructs a URL defining the connection target. The constructor takes one or more `String` objects as parameters. Here a `String` variable defining the OPMN lookup URL containing the data needed to access an OPMN-managed OC4J instance is passed to the constructor:

      String url="service:jmx:rmi///opmn://oc4jhost1:6003/home"
      ...
      JMXServiceURL serviceUrl= new JMXServiceURL(url);

  See "Setting the JMX Service URI for an OPMN-Managed OC4J Instance" for instructions on connecting to an OPMN-managed OC4J instance running as a component of Oracle Application Server.

  See "Setting the JMX Service URI for a Standalone OC4J Instance" for instructions on connecting in a standalone OC4J environment.

- `javax.management.MBeanServerConnection` interface

  Defines the proxy for performing operations on the OC4J MBeanServer.

In addition to these JMX classes and interfaces, the `oracle.oc4j.admin.jmx.remote.api.JMXConnectorConstant` class is imported to make constants used by OC4J JMX connector clients available. Rather than importing this class, you may want to use the keys defined in this class directly in your code to avoid introducing Oracle APIs into your code. The constants defined in the class are:

- `CREDENTIALS_LOGIN_KEY`

  Stores a server login name.

- `CREDENTIALS_PASSWORD_KEY`

  Stores a server login password.

- `LOCALE`

  Stores a `Locale` used to localize MBean metadata, attributes and methods accessed via the connection. See "Setting a Locale" for details on localizing a connection instance.

- `HTTP_TUNNELING`

  Stores a Boolean value indicating whether HTTP tunneling is enabled. See "Enabling HTTP Tunneling" for details on enabling HTTP tunneling.

    // Import the JSR-160 classes and interfaces from jmx_remote_api.jar
    import javax.management.remote.JMXConnector;
    import javax.management.remote.JMXServiceURL;
    import javax.management.remote.JMXConnectorFactory;

    // Import the JMX 1.2 class
    import javax.management.MBeanServerConnection;

    // Import OC4J specific constant values. You can optionally use
    // the values specified in this class to avoid introducing
    // any Oracle-specific code.
    import oracle.oc4j.admin.jmx.remote.api.JMXConnectorConstant;

    ....
    // Create a variable for a URL containing data needed to access
    // the connection target; in this case, an OPMN-managed OC4J instance
    String url="service:jmx:rmi///opmn://opmnhost1.company.com:6003/home"

    JMXConnector jmxCon= null;

    try {
    // Define the connection target
    JMXServiceURL serviceUrl= new JMXServiceURL(url);

    // Use to pass environment properties to be used while
    // retrieving a connection
    Hashtable env= new Hashtable();

    // Define the provider root package
    env.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
     "oracle.oc4j.admin.jmx.remote");

    Hashtable credentials= new Hashtable();

    // Connect using the oc4jadmin super-user administrator account
    credentials.put(JMXConnectorConstant.CREDENTIALS_LOGIN_KEY,"oc4jadmin");
    credentials.put(JMXConnectorConstant.CREDENTIALS_PASSWORD_KEY,"password");

    // Specify the login/password to use for the connection
    env.put(JMXConnector.CREDENTIALS, credentials);

    // Get an instance of the JMXConnector interface for OC4J's rmi protocol
    // User is not yet connected
    jmxCon = JMXConnectorFactory.newJMXConnector(serviceUrl, env);

    // Connect to the target OC4J instance defined in the JMXServiceURL
    jmxCon.connect();

    // Retrieve the MBeanServerConnection instance that acts as a proxy
    // for the OC4J MBeanServer we are connecting to.
    MBeanServerConnection con= jmxCon.getMBeanServerConnection();

    // Use the MBeanServerConnection instance to perform remote
    // operations on the OC4J MBeanServer. This call retrieves
    // all MBeans registered with the server.
    Set mbeans= con.queryNames(null, null);

    // Display each MBean's ObjectNameIterator iter= mbeans.iterator();
    while(iter.hasNext())
    System.out.println(iter.next().toString());
    }

    // Important!!! Release the connection, ideally using a Finally block
    finally {
    if(jmxCon!=null)
     jmxCon.close();
    }

#### Connecting to an Application-Specific MBean Server

Applications can create and connect to a generic MBeanServer instance, instead of using the OC4J MBeanServer. This is useful, for example, when creating applications that must be portable to multiple J2EE containers, not just OC4J.

In this scenario, you will supply the default domain for the MBeanServer. The MBeanServer instance will be created and registered with the MBeanServerFactory.

The example below creates and registers an MBeanServer instance under the domain "myserv". The code specific to this MBeanServer instance is highlighted as bold.

    // Import the JSR-160 classes and interfaces from jmx_remote_api.jar
    import javax.management.remote.JMXConnector;
    import javax.management.remote.JMXServiceURL;
    import javax.management.remote.JMXConnectorFactory;

    // Import the JMX 1.2 class
    import javax.management.MBeanServerConnection;

    // Import OC4J specific constant values. You can optionally use
    // use the values specified in this class to avoid introducing
    // any Oracle-specific code.
    import oracle.oc4j.admin.jmx.remote.api.JMXConnectorConstant;

    ....
    // Create a variable for a URL containing data needed to access
    // the connection target; in this case, an OPMN-managed OC4J instance
    String url="service:jmx:rmi///opmn://opmnhost1.company.com:6003/home"

    JMXConnector jmxCon= null;

    try {
    // Define the connection target
    JMXServiceURL serviceUrl= new JMXServiceURL(url);

    // Use to pass environment properties to be used while
    // retrieving a connection
    Hashtable env= new Hashtable();

    // Define the provider root package
    env.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
     "oracle.oc4j.admin.jmx.remote");

    Hashtable credentials= new Hashtable();

    // Connect using the oc4jadmin administrator account
    credentials.put(JMXConnectorConstant.CREDENTIALS_LOGIN_KEY,"oc4jadmin");
    credentials.put(JMXConnectorConstant.CREDENTIALS_PASSWORD_KEY,"password");

    // Specify the login/password to use for the connection
    env.put(JMXConnector.CREDENTIALS, credentials);

    // Specify the application-specific MBeanServer default domain name
    // used at creation time for the MBeanServer the application will connect to.
    // The domain name specified here is "myserv".
    env.put(JMXConnectorConstant.PROPRIETARY_MBEANSERVER_DOMAIN_NAME, "myserv");

    // Get an instance of the JMXConnector interface for OC4J RMI protocol
    // User is not yet connected
    jmxCon = JMXConnectorFactory.newJMXConnector(serviceUrl, env);

    // Connect to the target OC4J instance defined in the JMXServiceURL
    jmxCon.connect();

    // Retrieve the MBeanServerConnection instance that acts as a proxy
    // for the OC4J MBeanServer we are connecting to.
    MBeanServerConnection con= jmxCon.getMBeanServerConnection();

    // Use the MBeanServerConnection instance to perform remote
    // operations on the OC4J MBeanServer. This call retrieves
    // all MBeans registered with the server.
    Set mbeans= con.queryNames(null, null);

    // Display each MBean's ObjectNameIterator iter= mbeans.iterator();
    while(iter.hasNext())
    System.out.println(iter.next().toString());
    }

    // Important!!! Release the connection, ideally using a Finally block
    finally {
    if(jmxCon!=null)
     jmxCon.close();
    }

#### Connecting to a Specific Application's JMX Domain

Because users assigned to the `oc4j-administrators` role can access all MBeans registered with the MBeanServer, assigning this role to all users may not be desirable.

You can, however, enable a user that is not assigned this role to access only those MBeans registered by your application. In this case, the user connects at the application level, and will only see MBeans registered by the application.

The code is the same as that outlined in "Connecting to the OC4J MBeanServer" above, except the `url` passed to the `JMXServiceURL` constructor includes the name of the application. The following example will provide access to MBeans registered by the `hello-world` application:

    // Create a variable for a URL containing data needed to access
    // the connection target; in this case, an OPMN-managed OC4J instance
    String url="service:jmx:rmi///opmn://opmnhost1.company.com:6003/home/hello-world"

    JMXConnector jmxCon= null;

    try {
    // Define the connection target
    JMXServiceURL serviceUrl= new JMXServiceURL(url);
    ...

See "Setting the JMX Service URI for an OPMN-Managed OC4J Instance" for instructions on connecting to an OPMN-managed OC4J instance running as a component of Oracle Application Server.

See "Setting the JMX Service URI for a Standalone OC4J Instance" for instructions on connecting in a standalone OC4J environment.

#### Setting the JMX Service URI for an OPMN-Managed OC4J Instance

In an Oracle Application Server environment, the RMI port for an OC4J instance - required for a JMX connection - is not fixed and can change each time the instance is started by OPMN.

To resolve this issue, an OPMN-based URL must be passed to the `JMXServiceURL` constructor. This URL provides an indirect lookup with OPMN and returns the RMI port required for the connection.

The syntax of the OPMN lookup URI used to connect to the MBeanServer on a specific OPMN-managed OC4J instance is as follows:

    service.jmx:rmi:///opmn://opmnHost:[opmnPort]/oc4jInstanceName/[appName]

To connect to the cluster MBeanServer, specify the following URI. Note the inclusion of `/cluster`, indicating that the connection is with the cluster MBeanServer, rather than a specific OC4J instance's MBeanServer:

    service.jmx:rmi:///opmn://opmnHost:[opmnPort]/cluster/[ASInstanceName
    /[Oc4jCompName]

Note that while the `ASInstanceName` and `Oc4jCompName` parameters are optional, it is highly recommended that you do specify an Oracle Application Server and/or OC4J instance to connect to. Otherwise, a connection is made with a randomly-selected OC4J process within the cluster. This can result in the creation of a new instance of the cluster MBeanServer each time a new connection is obtained.

The recommended practice is to specify both `ASInstanceName` and `Oc4jCompName`, as a connection will be obtained with a single instance of the cluster MBeanServer. Because OPMN will automatically restart the OC4J process if needed, the process is guaranteed to always be available.

For example, the following example connects to clusterMBeanServer within the `admin` OC4J instance on the `as101` Oracle Application Server instance:

    service:jmx:rmis:///opmn://stadp69:6003/cluster/as101/admin

The cluster MBeanServer service URI parameters and their values are described in the table below.

Table 5-1 URI parameters

Parameter | Value
--- | ---
`hostname` | The name of the OPMN host, such as `oc4jhost1`. This value is required.
`port` | The OPMN request port. This value is specified in the `request` attribute of the `<port>` element in `opmn.xml`. If not specified, the default value `6003` is used.
`oc4jInstanceName` | Valid for a specific OC4J MBeanServer only. The name of the OC4J instance. This value is required. The name of the default OC4J instance created in Oracle Application Server is `home`. Specify`/home` to connect to this instance on the target host.
`appName` | Valid for a specific OC4J MBeanServer only. The optional name of a specific application to access, such as `/petstore`. If not specified, an unrestricted connection to all applications is returned. This option is used to allow users not assigned the `oc4j-administrators` role to access a specific application's MBeans. Because the connection is made at the application level, the user has access only to those MBeans registered by the application.
`ASInstanceName` | Valid for a cluster MBeanServer only. The optional name of an Oracle Application Server instance to connect to. This value is specified in the `id` attribute of the `<ias-instance>` element in `opmn.xml`.
`Oc4jCompName` | Valid for a cluster MBeanServer only. The name of an OC4J instance to connect to. This value is specified in the `id` attribute of the `<process-type>` element in `opmn.xml`. If this parameter is specified without ASInstanceName, the port parameter must be supplied for the Oracle Application Server instance the OC4J instance is running within.

The following URL provides unrestricted JMX access to all application MBeans deployed into the `home` OC4J instance on the specified host. Note that the port value is omitted, meaning the default will be used:

    service:jmx:rmi///opmn://opmnhost1/home

The next example provides access only to MBeans registered by the `petstore` application. The connection target is the `home02` instance on the specified host. Note that the port value has been specified:

    service:jmx:rmi///opmn://opmnhost1:6008/home02/petstore

#### Setting a Secure JMX Service URI for an OPMN-Managed OC4J Instance

The following URI accesses the cluster MBeanServer:

    service:jmx:rmis:///opmn://opmnHost:opmnPort/cluster/[ASInstanceName]/Oc4jCompName

#### Setting the JMX Service URI for a Standalone OC4J Instance

In a standalone OC4J installation, in which OC4J is installed, managed, started and stopped directly as a self-contained component, the RMI port is fixed. A URL containing connection parameters can be passed to the `JMXServiceURL` constructor to connect directly to the OC4J server.

The syntax of the lookup URL used in a standalone OC4J installation is as follows:

    service.jmx:rmi://[hostname]:[rmiPort/]oc4jContextRoot/[appName]

For example:

    service:jmx:rmi://oc4jhost:23791/oc4j/petstore

The URL parameters and their values are described in the table below.

Table 5-2 URL parameters

Parameter | Value
--- | ---
`hostname` | Optional. The name of the OC4J host, such as `oc4jhost1`. Defaults to `localhost` if not specified.
`rmiPort` | Optional. The RMI port to connect to. If not specified, the value defaults to `23791`.
`oc4jcontextRoot` | Required. The URL path to the OC4J installed directory on the server (`"/oc4j"`). The `/oc4j` context URI is used to identify the OC4J instance's local MBeanServer instance. This value is required.
`appName` | Optional. The name of a specific application to access, such as `/petstore`. If not specified, an unrestricted connection to all applications is returned. This option is used to allow users not assigned the `oc4j-administrators` role to access a specific application's MBeans. Because the connection is made at the application level, the user has access only to those MBeans registered by the application.

#### Setting a Secure JMX Service URI for a Standalone OC4J Instance

You can use ORMI over SSL, or ORMIS, to secure the connection between the management client and the OC4J MBeanServer. To use this feature, simply replace `rmi` with `rmis` in the JMX service URI syntax illustrated above. Note that the ORMIS port `23943` is specified.

For example:

    service:jmx:rmis://oc4jhost:23943/oc4j/petstore

The target OC4J server must be configured to use ORMIS. See the Oracle Containers for J2EE Security Guide for instructions on enabling ORMIS.

#### Setting a Locale

A specific `Locale` can be associated with a connection by setting an additional environment property passed to either the `JMXConnectorFactory.newJMXConnector()` or `JMXConnector.connect()` method. The `LOCALE` constant of the OC4J-specific `oracle.oc4j.admin.jmx.api.JMXConnectorConstant` class can be used to set this property. For example:

    env.put(JMXConnectorConstant.LOCALE, Locale.FRENCH)

Note that for localization to be used, the MBeans to be managed must support localization as outlined in "Adding Localization Support to Your MBeans".

#### Enabling HTTP Tunneling

In scenarios where the client, the OC4J server or both are secured behind firewalls that allow only HTTP traffic, the JMX RMI connector can be configured to tunnel RMI traffic over HTTP, enabling communication across firewalls.

In HTTP tunneling, RMI calls are encapsulated within an HTTP `POST` request. Replies are similarly returned as HTTP-encapsulated data.

HTTP tunneling is enabled by setting the value of the `HTTP_TUNNELING` constant of the `oracle.oc4j.admin.jmx.api.JMXConnectorConstant` class to the path of the `rmiTunnel` servlet and passing it as an environment property to either the `JMXConnectorFactory.newJMXConnector()` or `JMXConnector.connect()` method. For example:

    env.put(JMXConnectorConstant.HTTP_TUNNELING, "j2ee/rmiTunnel")

Note that the port value in the `JMXServiceURL` object used to get a `JMXConnection` instance must be set to the HTTP port of the target OC4J instance, and not the RMI port, as shown in previous connection examples. The OC4J default HTTP listener port is `8888` in OC4J standalone, or `7777` in an Oracle Application Server environment.

    JMXServiceURL serviceUrl= new JMXServiceURL("rmi","oc4j-sun.acme.com", 8888,"/oc4j");

See the Oracle Containers for J2EE Services Guide for instructions on configuring RMI HTTP tunneling in OC4J.

## Sample MBean

The following is an example of a simple MBean implementation. This MBean includes operations to enable or disable a user within the application it is packaged with.

### UserManagerMBean Interface

This is the Java interface for the MBean.

    package demo.servicereq.management;

    public interface UserManagerMBean {
      String[] listUsers();
      void enableUser(int userId);
      void disableUser(int userId);
    }

### UserManager Implementation Class

This is the MBean implementation class.

    package demo.servicereq.management;

    import oracle.srdemo.data.User;
    import oracle.srdemo.data.UserAccess;
    import java.util.Collection;
    import java.util.logging.Level;
    import javax.management.MBeanNotificationInfo;
    import javax.management.Notification;
    import javax.management.NotificationBroadcasterSupport;
    import java.util.logging.Logger;
    import java.util.Iterator;

    public class UserManager
           extends NotificationBroadcasterSupport
           implements UserManagerMBean {

     private static final String m_classname =
     UserManager.class.getClass().getName();

     public static final String ENABLE_USER = "enableUser"; public static final String DISABLE_USER = "disableUser";
     public static final String LIST_USERS = "listUsers";
     String[] m_users;

      // A logger
      private static final Logger m_logger = Logger.getLogger(m_classname);

     /**   * Constructor.
       */
      public UserManager()  {
      }

      /**
       * Lists all the user names.
       * @return
       */
      public String[] listUsers() {
        m_logger.entering(m_classname,"listUsers");
        // query all users and return
        m_logger.exiting(m_classname,"listUsers");
        return m_users;
      }

    /**   * Sets the specified user to a state of enabled.
       * @param userId
       */
      public void enableUser(int userId) {
        m_logger.entering(m_classname,"enableUser");
        sendNotification(ENABLE_USER, "userId [" + userId + "] now enabled");
        // Lookup user with userId.
        // Set the status of the user to enabled.
        // throw exception if user doesn't exist.
        m_logger.exiting(m_classname,"enableUser");
      }

    /**
       * Sets the specified user to a state of disabled.
       * @param userId
       */
      public void disableUser(int userId) {
        m_logger.entering(m_classname,"disableUser");
        sendNotification(DISABLE_USER, "userId [" + userId + "] now disabled");
        // Lookup user with userId.
        // Set the status of the user to enabled.
        // throw exception if user doesn't exist.
        m_logger.exiting(m_classname,"disableUser");
      }

    /**
        * Informs any interested party on what notifications this MBean emits.
        * @return the notifications this MBean emits
        */
      public MBeanNotificationInfo[] getNotificationInfo() {
        m_logger.entering(m_classname,"getNotificationInfo");
        String NOTIFICATIONS[] =
        { ENABLE_USER, DISABLE_USER };
        MBeanNotificationInfo[] info =
        {       new MBeanNotificationInfo(NOTIFICATIONS,
                                    "javax.management.Notification",
                                    "Notification set for UserManager") };
        m_logger.exiting(m_classname,"getNotificationInfo");
        return info;  }

     /**
       * Sends a JMX notification using the sendNotification method
       * from the base class.   * @param operation - the name of the operation sending the notification.
       * @param desc - the description to place within the notification.
       * @return void
       */
      public void sendNotification(String operation, String desc) {
        m_logger.entering(m_classname,"sendNotification");
        Notification notification = new Notification(operation,this,
        System.currentTimeMillis(), desc);
        super.sendNotification(notification);
        m_logger.exiting(m_classname,"sendNotification");
      }

    }

## Adding Localization Support to Your MBeans

All Dynamic MBeans - including Model and Open MBeans - must provide metadata describing the MBean as well as each of its exposed attributes and operations. If your application will be marketed internationally, you should design your MBeans to support localization of this metadata.

For additional information on localization with resource bundles, read the following article from Sun Microsystems:

`http://java.sun.com/developer/technicalArticles/Intl/ResourceBundles/`

### Localization Support Provided By Oracle

The `oracle.j2ee.admin.jmx` API extends the JMX specification with functionality specific to localizing MBeans. Note that any MBeans that use this API must be specific to OC4J, and will not be portable to other J2EE containers.

The localization-specific interface and class are covered below.

JMXState

The `oracle.j2ee.admin.jmx.JMXState` interface defines the state associated with a JMX operation, specifically the state of the `Locale` instance to be used. This state can be retrieved by an MBean implementation to provide localization support.

This interface contains a single method, which returns the `Locale` instance:

`public Locale getLocale()`

JMXStateFactory

The `oracle.j2ee.admin.jmx.JMXStateFactory` class provides access to the state associated with a JMX operation, such as the `Locale` object to be used. It includes the following method:

- `public static JMXState getJMXState()`

  Retrieves the `oracle.j2ee.admin.jmx.JMXState` instance containing the JMX state associated with the calling JMX MBean operation. This method should only be called from within an MBean implementation.

### Using Resource Bundles to Localize MBean Metadata

Localization is enabled using resource bundles, which are objects of the `java.util.ResourceBundle` class. A resource bundle consists of one or more Java classes or Java `properties` files containing key/value pairs, where the value is a string comprising the descriptive text. A resource bundle will typically exist for each supported language.

The following example is a snippet from the default OC4J`Messages.properties` file showing how the metadata for a sample `UserManager` MBean is stored as key/value pairs. The keys correspond to values set in the code sample that follows.

    //Description of the MBean
    usermanager_description=Manages users of the corresponding installation.

    //Attribute description strings
    This MBean does not have attributes.

    //Operation description strings
    usermanager_listUsers=List current user IDs.
    usermanager_enableUser=Enables the specified user account.
    usermanager_disableUser=Disables the specified user account.

    //Operation parameter description strings
    usermanager_userId=The user account to affect.

See Localization with Resource Bundles at the following URL for more on resource bundle implementation:

    http://java.sun.com/developer/technicalArticles/Intl/ResourceBundles/

Note: OC4J uses Java classes to localize the metadata for its own components, including Oracle-supplied MBeans. Do not make changes to the default `Messages.properties` file used by OC4J. Any changes made to this file will be overwritten whenever a new version of OC4J is installed.

### Adding Localization Support to Your MBeans

To expose its metadata, an MBean must implement the overloaded `getMBeanInfo()` method, which returns an object of the `javax.management.MBeanInfo` object populated with generic metadata for the attributes and operations exposed by the MBean.

A Dynamic MBean must implement the generic version of this method to retrieve and localize its metadata using the `Locale` object from the JMX client. The implementation of a Model MBean - an object of the `javax.management.modelmbean.RequiredModelMBean` class - must also implement this generic signature. See "Implementing the Generic getMBeanInfo() Signature" for details.

MBeans supporting localization must also expose the signature `getMBeanInfo(Locale locale)`, which retrieves and localizes the metadata based on the Locale passed in by the OC4J MBeanServer. See "Exposing the Required getMBeanInfo(Locale locale) Signature"

Implementing the Generic getMBeanInfo() Signature

To localize the returned metadata, the generic `getMBeanInfo()` method must get access to the `Locale` object from the JMX client. The `getLocale()` method of the `oracle.j2ee.admin.jmx.JMXState` interface can be used to accomplish this. Your bean should also import the `oracle.oc4j.admin.jmx.JMXStateFactory` class, which provides access to the state associated with a JMX operation, such as the `Locale` object to be used.

The following example illustrates implementation of this method in a Simple MBean.

    package demo.servicereq.management;

    import oracle.srdemo.data.User;
    import oracle.srdemo.data.UserAccess;
    import java.util.Collection;
    import java.util.logging.Level;
    import javax.management.MBeanNotificationInfo;
    import javax.management.Notification;
    import javax.management.NotificationBroadcasterSupport;
    import java.util.logging.Logger;
    import java.util.Iterator;

    // Import packages needed for localization of MBean metadata
    import java.util.Locale;
    import java.util.ResourceBundle;
    import javax.management.MBeanInfo;

    // Import the Oracle localization APIs
    import oracle.j2ee.admin.jmx.JMXStateFactory;
    import oracle.j2ee.admin.jmx.JMXState;

    public class UserManager
           extends NotificationBroadcasterSupport
           implements UserManagerMBean {

    // Create the MBeanInfo object to allow attributes and operations exposed by the
    // MBean to be retrieved
    public MBeanInfo getMBeanInfo()
      {
        // Get access to the Locale instance set by the JMX client
        Locale locale = JMXStateFactory.getJMXState().getLocale();

        // Create MBean's localized meta-data using the locale from JMX client
        return createMBeanInfo(locale);
      }

Exposing the Required getMBeanInfo(Locale locale) Signature

All MBeans deployed into OC4J, regardless of type, are required to expose the `getMBeanInfo(Locale locale)` signature, which retrieves and localizes the MBean's metadata based on the `Locale` object passed in as a parameter. This method will be called by clients such as the System MBean Browser component of the Application Server Control Console as well as the Oracle JSR-160 connector, which is used for remote management of MBeans.

The method allows support of localized `MBeanInfo` without requiring any modification to the default `getMBeanInfo()` method, such as introducing the Oracle specific `JMXState` class. As such, it allows you to write localized code that remains portable, although the proper localization will only work within Oracle Application Server.

The following example illustrates implementation of both signatures of `getMBeanInfo()` in a Dynamic MBean.

    package demo.servicereq.management;

    import oracle.srdemo.data.User;
    import oracle.srdemo.data.UserAccess;
    import java.util.Collection;
    import java.util.logging.Level;
    import javax.management.MBeanNotificationInfo;
    import javax.management.Notification;
    import javax.management.NotificationBroadcasterSupport;
    import java.util.logging.Logger;
    import java.util.Iterator;

    // Import the Oracle localization APIs
    import oracle.j2ee.admin.jmx.JMXStateFactory;
    import oracle.j2ee.admin.jmx.JMXState;

    public class UserManager
           extends NotificationBroadcasterSupport
           implements UserManagerMBean {

    // Create the MBeanInfo object to allow attributes and operations exposed by the
    // MBean to be retrieved
    public MBeanInfo getMBeanInfo()
    {
      // Get access to the Locale instance set by the JMX client
      Locale locale = JMXStateFactory.getJMXState().getLocale();

      // Create MBean's localized metadata using the Locale set by the JMX client
      return createMBeanInfo(locale);
    }

    // Expose the Dynamic MBean operation
    public MBeanInfo getMBeanInfo(Locale locale)
    {
      // Create MBean's metadata using the Locale from the MBeanServer
      return createMBeanInfo(locale);
    }

In this example, both signatures of `getMBeanInfo()` pass the `Locale` instance to the private `createMBeanInfo(Locale locale)` method, which retrieves the appropriate resource bundle containing the descriptions of the MBean, its attributes and its operations. Note that this method also sets the localized description for each of the operation's parameters. It then creates the `MBeanInfo` object containing the localized metadata.

    package demo.servicereq.management;

    import java.util.Locale;

    import java.util.ResourceBundle;

    import javax.management.MBeanConstructorInfo;
    import javax.management.MBeanInfo;

    import javax.management.MBeanOperationInfo;

    import javax.management.MBeanParameterInfo;

    import oracle.srdemo.data.User;
    import oracle.srdemo.data.UserAccess;
    import java.util.Collection;
    import java.util.logging.Level;
    import javax.management.MBeanNotificationInfo;
    import javax.management.Notification;
    import javax.management.NotificationBroadcasterSupport;
    import java.util.logging.Logger;
    import java.util.Iterator;

    // Import the Oracle localization APIs
    import oracle.j2ee.admin.jmx.JMXStateFactory;
    import oracle.j2ee.admin.jmx.JMXState;

    public class UserManager        extends NotificationBroadcasterSupport
           implements UserManagerMBean {

            private static final String m_classname =
     UserManager.class.getClass().getName();

     public static final String ENABLE_USER = "enableUser";
     public static final String DISABLE_USER = "disableUser";
     public static final String LIST_USERS = "listUsers";

      String[] m_users;

      // A logger
      private static final Logger m_logger = Logger.getLogger(m_classname);

     /**
       * Constructor.
       */
         public UserManager()  {
      }
        /**
       * Lists all the user names.
       * @return
       */
      public String[] listUsers() {
        m_logger.entering(m_classname,"listUsers");
        // query all users and return
        m_logger.exiting(m_classname,"listUsers");
        return m_users;
      }

    /**   * Sets the specified user to a state of enabled.
       * @param userId
       */
      public void enableUser(int userId) {
        m_logger.entering(m_classname,"enableUser");
        sendNotification(ENABLE_USER, "userId [" + userId + "] now enabled");

        // Lookup user with userId.
        // Set the status of the user to enabled.
        // throw exception if user doesn't exist.
        m_logger.exiting(m_classname,"enableUser");
      }

    /**
       * Sets the specified user to a state of disabled.
       * @param userId
       */
      public void disableUser(int userId) {
        m_logger.entering(m_classname,"disableUser");
        sendNotification(DISABLE_USER, "userId [" + userId + "] now disabled");
        // Lookup user with userId.
        // Set the status of the user to enabled.
        // throw exception if user doesn't exist.
        m_logger.exiting(m_classname,"disableUser");
      }

    /**
        * Informs any interested party on what notifications this MBean emits.
        * @return the notifications this MBean emits
        */  public MBeanNotificationInfo[] getNotificationInfo() {    m_logger.entering(m_classname,"getNotificationInfo");
        String NOTIFICATIONS[] =
        { ENABLE_USER, DISABLE_USER };
        MBeanNotificationInfo[] info =
        {
          new MBeanNotificationInfo(NOTIFICATIONS,
                                    "javax.management.Notification",
                                    "Notification set for UserManager") };
        m_logger.exiting(m_classname,"getNotificationInfo");
        return info;
      }

     /**
       * Sends a JMX notification using the sendNotification method
       * from the base class.
       * @param operation - the name of the operation sending the notification.
       * @param desc - the description to place within the notification.
       * @return void
       */
      public void sendNotification(String operation, String desc) {
        m_logger.entering(m_classname,"sendNotification");
        Notification notification = new Notification(operation,this,
        System.currentTimeMillis(), desc);
        super.sendNotification(notification);
        m_logger.exiting(m_classname,"sendNotification");
      }

    // Create the MBeanInfo object to allow attributes and operations exposed by the
    // MBean to be retrieved
    public MBeanInfo getMBeanInfo()
    {
      // Get access to the Locale instance set by the JMX client
        Locale locale;
        locale = JMXStateFactory.getJMXState().getLocale();

        // Create MBean's localized metadata using the Locale from JMX client
      return createMBeanInfo(locale);
    }

    // Create the MBeanInfo object to allow attributes and operations exposed by the
    // MBean to be retrieved
    public MBeanInfo getMBeanInfo(Locale locale)
    {
      // Create the MBean's metadata using the Locale from the MBeanServer
      return createMBeanInfo(locale);
    }

    // Create the MBean's localized metadata
    private MBeanInfo createMBeanInfo(Locale locale)
    {  // Get the resource bundle for the specified locale
      ResourceBundle resource =
        ResourceBundle.getBundle("mymbeans/Messages", locale);

      MBeanInfo minfo = null;
      try
       {

       // Set the MBean constructor descriptor
          consInfoArray_ = new MBeanConstructorInfo[0];

       // Set the MBean operations descriptor

       MBeanOperationInfo[] operInfoArray_ = new MBeanOperationInfo[]{ };
          MBeanParameterInfo params;
          params = new MBeanParameterInfo[];

          // Set the description for the userId parameter
          params[0] = new MBeanParameterInfo("userId",
                     resource.getString("usermanager_userId"));

          // Set the description for the listUsers operation      operInfoArray_[0] = new MBeanOperationInfo("listUsers",
                              resource.getString("usermanager_listUsers"),
                                                     params,
                                                     "",
                                                     MBeanOperationInfo.ACTION)

          // Set the description for the enableUser operation
          operInfoArray_[1] = new MBeanOperationInfo("enableUser",
                              resource.getString("usermanager_enableUser"),
                                                     params,
                                                     "",
                                                     MBeanOperationInfo.ACTION)

          // Set the description for the disableUser operation
          operInfoArray_[2] = new MBeanOperationInfo("disableUser",
                              resource.getString("usermanager_disableUser"),
                                                     params,
                                                     "",
                                                     MBeanOperationInfo.ACTION)

       // Create the MBeanInfo object containing the localized metadata
       // The null parameter is for notifications, which are not provided by this
       // MBean
       MBeanInfo minfo = new MBeanInfo("MyManager",
                                resource.getString("mymanager_description"),
                                attribInfoArray_,
                                consInfoArray_,
                                operInfoArray_,
                                null);
       }
       catch
       {
       // Handle exceptions
      }
    return minfo;
    }