Skip Headers
Oracle® Containers for J2EE Developer's Guide
10g Release 3 (10.1.3)
Part No. B14433-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
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?

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:

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

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:

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 thejavax.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:

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

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

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;
}