Contents | Previous | Next | Java Management Extensions (JMX) Technology Tutorial

## Chapter 4

## Lookup Services

The Java Management Extensions (JMX) specification defines three bindings to lookup services, using existing lookup technologies, as described in the following sections:

- Section 4.1 "Initial Configuration" provides configuration information that applies to all three types of lookup service.
- Section 4.2 "Service Location Protocol (SLP) Lookup Service" presents the SLP lookup example.
- Section 4.3 "Jini Lookup Service" presents the Jini lookup example.
- Section 4.4 "Java Naming and Directory Interface (JNDI) / LDAP Lookup Service" presents the JNDI/LDAP lookup example.

The lookup services allow JMX technology clients to find and connect to connector servers that have registered with the lookup services.

## 4.1 Initial Configuration

As shown simply in Section 3.1 "Accessing Standard and Dynamic MBeans via the RMI Connector", if you are using remote method invocation (RMI) connectors, you can choose to use an external directory to register the connector server stubs you want to look up. The following cases are presented in the lookup service examples relating to RMI connectors:

- RMI connectors using one of the following external directories:

- An RMI registry, for RMI connectors implementing the default Java Remote Method Protocol (JRMP) transport
- CORBA Naming Service, for RMI connectors implementing the Internet Inter-ORB Protocol (IIOP) transport
- Lightweight Directory Access Protocol (LDAP), for both the IIOP and JRMP transports

- RMI connectors without an external directory

If you choose to register the RMI connector stubs in an external directory, some initial configuration is required, to set up your RMI registry, CORBA naming service or LDAP server. If you do not use an external directory, the RMI connector stub is encoded into the JMX service URL.

The following sections describe the external directories that you can use in conjunction with the lookup service examples that use RMI connectors. These external directories are referred to when running the three examples of lookup services that are given in the subsequent sections in this chapter.

### 4.1.1 External RMI Registry

To register the RMI connector server stubs in an external RMI registry, for use by connectors implementing the JRMP transport, perform the following actions:

1. Start the RMI registry on port 9999 of the local host.

As was the case in Chapter 3, "JMX Connectors", the RMI registry is used to store the RMI connector stubs for RMI connectors implementing the JRMP transport.

`$` rmiregistry 9999 &

2. For your convenience when typing commands, create an environment variable for the address of the RMI registry.

To shorten the commands that you will type when you run the examples, set the service URL for the RMI registry as an environment variable, `jndirmi`. In these examples, the service URL is given in JNDI form. See the API documentation for the `javax.management.remote.rmi` package for an explanation of JNDI form. If you want to run the external directories on a machine other than the local machine, you must specify that machine’s host name instead of localhost.

`$` jndirmi="rmi://localhost:9999"

### 4.1.2 External CORBA Naming Service

To register the RMI connector server stubs in an external CORBA naming service, for use by connectors implementing the IIOP transport, perform the following actions:

1. Start an Object Request Broker (ORB) daemon on port 7777 of the local host.

RMI connectors that implement the IIOP transport can use CORBA naming to identify the RMI connector stub.

`$` orbd -ORBInitialPort 7777 &

2. For your convenience when typing commands, create an environment variable for the address of the CORBA naming service.

To shorten the commands that you type when you run the examples, set the service URL for the CORBA naming service as an environment variable, jndiiiop. In these examples, the service URL is given in JNDI form. If you want to run the external directories on a machine other than the local machine, you must specify that machine’s host name instead of localhost.

`$` jndiiiop="iiop://localhost:7777"

### 4.1.3 External LDAP Registry

To register the RMI connector server stubs in an external LDAP registry, for use by connectors implementing either of the JRMP or IIOP transports, perform the following actions:

1. Start an LDAP Server.

The LDAP server you use is your choice, although the schema for representing Java objects in an LDAP directory must be known to the server. See the relevant Request For Comments (RFC) document for details:

`http://www.ietf.org/rfc/rfc2713.txt`

2. Create a domain component suffix.

These examples require that you create the following domain component suffix:

`dc=Test`

See the documentation accompanying your LDAP server for details of how to configure the server and create this suffix.

3. For your convenience, set the following LDAP parameters as environment variables.

These variables are used to shorten the commands you type when starting the Server and Client classes in the lookup service examples that register RMI connector stubs in the external LDAP server.

1. The name of the machine running your LDAP server (ldap_host)

`$` ldaphost=ldap_host

2. The port the LDAP server is running on (ldap_port)

`$` ldapport=ldap_port

3. The LDAP common name attribute, which in these examples is “Directory Manager”

`$` principal=”cn=Directory Manager”

4. The password required by your LDAP server

Supply the password for your LDAP server.

`$` credentials=your_ldap_password

5. The address of the LDAP server

In this example, the service URL for the LDAP server is given in JNDI form and is identified by the variable jndildap.

`$` jndildap="ldap://$ldaphost:$ldapport"

4. You are now ready to run the different lookup service examples.

## 4.2 Service Location Protocol (SLP) Lookup Service

The JMX technology specifies how to register RMI connectors with the SLP lookup service.

The purpose of this example is to demonstrate how a JMX Remote API connector client can find and connect to a connector server that has registered with the SLP lookup service. This example performs the following operations:

1. The agent:

1. Creates an MBean server
2. Gets a pointer to the SLP lookup service
3. Creates a connector server
4. Registers the connector address with the SLP lookup service

2. The client:

1. Gets a pointer to the SLP lookup service
2. Looks for any connector servers registered in the SLP lookup service
3. Creates a JMX Remote API connector
4. Retrieves information about the MBeans in the MBean server

Note – This example assumes that you are already familiar with SLP technology. The code provided for this example conforms to Sun Microsystems’ implementation of SLP, as defined by RFC 2614 (see `http://www.ietf.org/rfc/rfc2614.txt`). Sun Microsystems’ implementation of SLP is available in the Solaris operating environment in the directory `/usr/share/lib/slp`. If you are not running the Solaris operating environment, you must obtain a version of SLP that is compliant with RFC 2614, section 5.

The SLP lookup example is contained in the directory work_dir`/jmx_examples/Lookup/slp`.

1. Open work_dir`/jmx_examples/Lookup/slp`.

Inside this directory, you will find the following files:

- `Server.java`
- `Client.java`
- `README`

2. Open both the `*.java` files in a text editor.

These classes will be analyzed in the following sections.

### 4.2.1 Analyzing the Example Classes

The following sections analyze each of the classes used in the SLP lookup example, and explain how they perform the operations described above.

Note – If you are using an implementation of SLP other than Sun Microsystems’ implementation, you will have to modify `Server.java` and `Client.java` to import your version of the SLP Java classes instead of the `com.sun.slp` package. See RFC 2614, section 5.

#### 4.2.1.1 Server.java

Due to its size, the SLP lookup service `Server.java` class is shown as a series of code excerpts. For explanations of the SLP code used in this example, see RFC 2614 and the API documentation for SLP.

CODE EXAMPLE 4-1 SLP Lookup Service Example Class Server.java (Excerpt 1)

    public class Server {
       public final static int JMX_DEFAULT_LEASE = 300;
       public final static String JMX_SCOPE = "DEFAULT";

       private final MBeanServer mbs;
       public Server() {
           mbs = MBeanServerFactory.createMBeanServer();
       }

    [...]

CODE EXAMPLE 4-1 sets the default SLP lease `JMX_DEFAULT_LEASE` to a default lease of 300 seconds, corresponding to the length of time the URL will be registered, and shows the initial creation of the MBean server `mbs`.

In code that is not shown here, you then define an SLP advertiser `slpAdvertiser`, and an SLP service URL `url`. The `slpAdvertiser` is used to register the service URL in the SLP lookup service. The `SCOPE` and the `agentName` are registered in SLP as lookup attributes.

CODE EXAMPLE 4-2 SLP Lookup Service Example Class Server.java (Excerpt 2)

    [...]

       public static void register(JMXServiceURL jmxUrl, String name)
         throws ServiceLocationException {
         ServiceURL serviceURL =
              new ServiceURL(jmxUrl.toString(),
                             JMX_DEFAULT_LEASE);
         debug("ServiceType is: " + serviceURL.getServiceType());
         Vector attributes = new Vector();
         Vector attrValues = new Vector();
         attrValues.add(JMX_SCOPE);
         ServiceLocationAttribute attr1 =
              new ServiceLocationAttribute("SCOPE", attrValues);
         attributes.add(attr1);
         attrValues.removeAllElements();
         attrValues.add(name);
         ServiceLocationAttribute attr2 =
              new ServiceLocationAttribute("AgentName", attrValues);
         attributes.add(attr2);
         final Advertiser slpAdvertiser =
              ServiceLocationManager.getAdvertiser(Locale.US);
         slpAdvertiser.register(serviceURL, attributes);

       }

    [...]

CODE EXAMPLE 4-2 shows the registration of the JMX connector server’s URL with the SLP lookup service.

The JMX service URL `jmxUrl` is the address of the connector server, and is obtained by a call to the `getAddress()` method of `JMXConnectorServer` when the connector server is started.

The SLP lookup attributes, namely the scope and the agent name under which the connector server address is to be registered (`name`), are then specified by the SLP class `ServiceLocationAttribute`. The `AgentName` attribute is mandatory, but other optional attributes, such as `ProtocolType`, `AgentHost`, and `Property` can also be registered in the SLP lookup service.

Finally, the JMX connector server address is registered in the SLP service with a call to the `register()` method of the `Advertiser` interface, with the `serviceURL` and the `attributes` passed in as parameters.

CODE EXAMPLE 4-3 SLP Lookup Service Example Class Server.java (Excerpt 3)

    [...]

       public JMXConnectorServer rmi(String url) throws
         IOException,
         JMException,
         NamingException,
         ClassNotFoundException,
         ServiceLocationException {
         JMXServiceURL jurl = new JMXServiceURL(url);
         final HashMap env = new HashMap();
         // Environment map attributes
         [...]

         JMXConnectorServer rmis =
            JMXConnectorServerFactory.newJMXConnectorServer(jurl, env, mbs);
         final String agentName = System.getProperty("agent.name",
                                                     "DefaultAgent");
         start(rmis, agentName);

         return rmis;
      }
    [...]

CODE EXAMPLE 4-3 shows the creation of an RMI connector server. The JMX service URL `jurl` is constructed from the string `url` that is included in the command used to launch the `Server` at the command line. An RMI connector server named `rmis` is then created with the system properties defined by the environment `map` and the address `jurl`.

The connector server is then started, and the RMI connector server addres is registered in the SLP lookup service under the name `agentName`.

CODE EXAMPLE 4-4 SLP Lookup Service Example Class Server.java (Excerpt 4)

    [...]

       public void start(JMXConnectorServer server, String agentName)
          throws IOException, ServiceLocationException {
          server.start();
          final JMXServiceURL address = server.getAddress();
          register(address,agentName);
       }

    [...]

CODE EXAMPLE 4-4 shows the launching of the connector server `server` and the registration of `server` in the SLP lookup service with the given address `address`.

#### 4.2.1.2 Client.java

The SLP lookup service `Client.java` class is shown in CODE EXAMPLE 4-5, CODE EXAMPLE 4-6, and CODE EXAMPLE 4-7:

CODE EXAMPLE 4-5 SLP Lookup Service Example Class Client.java (Excerpt 1)

    public class Client {

        public final static String JMX_SCOPE = "DEFAULT";

        public static Locator getLocator() throws ServiceLocationException {
          final Locator slpLocator =
              ServiceLocationManager.getLocator(Locale.US);
          return slpLocator;
        }

          public static List lookup(Locator slpLocator, String name)
              throws IOException, ServiceLocationException {

              final ArrayList list = new ArrayList();
              Vector scopes = new Vector();

              scopes.add(JMX_SCOPE);
              String query =
                  "(&(AgentName=" + ((name!=null)?name:"*") + "))";

              ServiceLocationEnumeration result =
                  slpLocator.findServices(new ServiceType("service:jmx"),
                                          scopes, query);

              while(result.hasMoreElements()) {
                    final ServiceURL surl = (ServiceURL) result.next();

                 JMXServiceURL jmxUrl = new JMXServiceURL(surl.toString());
                 try {
                      JMXConnector client =
                         JMXConnectorFactory.newJMXConnector(jmxUrl,null);
                      if (client != null) list.add(client);
                 } catch (IOException x ) {
                 [...]
                 }
              }
          }
          return list;
        }

CODE EXAMPLE 4-5 first of all obtains the SLP service `Locator` by calling the `getLocator` method of the SLP class `ServiceLocationManager`. `Client` then retrieves all the connector servers registered in the SLP service under a given agent name, or under agent names that match a certain pattern. If no agent name is specified when the `Client` is started, all agent names will be considered.

A JMX technology service URL, `jmxUrl`, is generated for each of the agents retrieved by SLP, with each agent’s SLP service URL, `surl`, passed as a parameter into the `JMXServiceURL` instance. The URL `jmxUrl` is then passed to the `newJMXConnector()` method of `JMXConnectorFactory`, to create a new connector client named `client` for each agent that is registered in the SLP service.

The connector clients retrieved are stored in an array list called `list`.

CODE EXAMPLE 4-6 SLP Lookup Service Example Class Client.java (Excerpt 2)

    public static void listMBeans(MBeanServerConnection server)
         throws IOException {

         final Set names = server.queryNames(null,null);
         for (final Iterator i=names.iterator(); i.hasNext(); ) {
              ObjectName name = (ObjectName)i.next();
              System.out.println("Got MBean: "+name);
              try {
                   MBeanInfo info =
                      server.getMBeanInfo((ObjectName)name);
                   MBeanAttributeInfo[] attrs = info.getAttributes();
                   if (attrs == null) continue;
                   for (int j=0; j<attrs.length; j++) {
                        try {
                             Object o =
                             server.getAttribute(name,attrs[j].getName());
                             System.out.println("\t\t" + attrs[j].getName() +
                             " = "+o);
                        } catch (Exception x) {
                             System.err.println("JmxClient failed to get " +
                                                 attrs[j].getName() + x);
                             x.printStackTrace(System.err);
                        }
         }
    }

In CODE EXAMPLE 4-6, a reference to the `MBeanServerConnection` is retrieved for every connector client that is created from the connector server address stored in the SLP service. A list of all the MBeans and their attributes is retrieved.

CODE EXAMPLE 4-7 SLP Lookup Service Example Class Client.java (Excerpt 3)

    public static void main(String[] args) {
          try {
               final String agentName = System.getProperty("agent.name");
               final Locator slpLocator = getLocator();
               List l = lookup(slpLocator,agentName);
               int j = 1;
               for (Iterator i=l.iterator();i.hasNext();j++) {
                    JMXConnector c1 = (JMXConnector) i.next();
                    if (c1 != null) {
                        try {
                             c1.connect(env);
                        } catch (IOException x) {
                             System.err.println ("Connection failed: " + x);
                             x.printStackTrace(System.err);
                             continue;
                        }

                        MBeanServerConnection conn =
                             c1.getMBeanServerConnection();

                        try {
                             listMBeans(conn);
                        } catch (IOException x) {
                             x.printStackTrace(System.err);
                        }
                        try {
                             c1.close();
                        } catch (IOException x) {
                             x.printStackTrace(System.err);
                        }
                    }
               }
          } catch (Exception x) {
               x.printStackTrace(System.err);
          }
    }

In CODE EXAMPLE 4-7, the `agent.name` property is retrieved by calling the `getProperty()` method of the `System` class, and the SLP lookup service is found by calling the `getLocator()` method of `Locator`.

All the agents named `agentName` are then looked up, and connections are made to the agents discovered. If no agent is specified, then all agents are lookup up. Connections are made to the MBean server created by `Server`, and all the MBeans in it are listed, before the connection is closed down.

### 4.2.2 Running the SLP Lookup Service Example

In addition to the actions you performed in Section 4.1 "Initial Configuration", before you can run the lookup service examples that use the SLP, you must perform some further initial actions that are specific to this example. You can then start looking up connectors using SLP in conjunction with the two connectors supported by the JMX technology.

When you run the examples, to help you keep track of which agent has been created with which transport, the agent names include a letter suffix that is the same as the lettering of the corresponding section. For example, the agent from Section a. "RMI connector over JRMP, without an external directory" is called `test-server-a`.

#### 4.2.2.1 Setting up the SLP Lookup Service Example

The following steps are required by all of the different transports you can run in this example.

1. For convenience when compiling and running the classes, define an additional environment variable.

In addition to the common environment variables that were set in Section 4.1 "Initial Configuration", you need to add the path to the SLP service. If you are using the Solaris operating enviornment, add the following variable:

`$` SLPLIB=/usr/share/lib/slp

If you are using another platform, set `SLPLIB` appropriately for the platform you are using.

2. Define and export the `classp` environment variable.

This example requires a classpath that includes the Java archive (JAR) files for SLP.

`$` classp=$SLPLIB/slp.jar

3. Compile the example `Client` and `Server` classes.

Type the following command:

`$` javac -d . -classpath $classp Server.java Client.java

4. Start the SLP daemon.

If you are using the Solaris operating environment, type the following command, which requires you to know your superuser password:

`$` su root -c "java -cp $SLPLIB/slpd.jar com.sun.slp.slpd &"

`Password:` [type superuser password]

If you are not running a Solaris system, start the SLP daemon according to the implementation of SLP you are using.

#### 4.2.2.2 Running the SLP Lookup Service Example

This example demonstrates the use of the SLP lookup service to look up RMI connector servers that use RMI’s default transport, JRMP, as well as the IIOP transport. In addition, as described in Section 4.1 "Initial Configuration", different external directories are used to register the RMI connector stubs.

The combinations of transports and external directories demonstrated here are:

- RMI connector over the JRMP transport, with:

- No external directory
- An RMI registry
- An LDAP registry

- RMI connector over the IIOP transport, with:

- No external directory
- A CORBA naming service
- An LDAP registry

Perform the following steps to run the example:

1. Start the `Server`.

The command you use to start the `Server` varies according to which external directory you are using. You can start one or more of the following instances of `Server` with different transports and external registries before starting the `Client`.

1. RMI connector over JRMP, without an external directory

Start `Server` by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-a \
      -Durl ="service:jmx:rmi://" \
      slp.Server &

In this command:

- `debug` is set to true to provide more complete screen output when the `Server` runs
- The name of the agent to be created is `test-server-a`
- The service URL specifies that the chosen connector is an RMI connector, running over the RMI default transport JRMP.

When Server is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the SLP service.

2. RMI connector over JRMP, using an RMI registry as an external directory.

Start `Server` by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-b \
      -Durl="service:jmx:rmi:///jndi/${jndirmi}/server" \
      slp.Server &

In this command:

- The name of the agent created is `test-server-b`
- The service URL specifies the chosen connector as RMI over JRMP, and the external directory in which the RMI connector stub, server, is stored is the RMI registry you identified as jndirmi in Section 4.1 "Initial Configuration".

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the SLP service.

3. RMI connector over JRMP, using LDAP as the external directory.

Start `Server` by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-c \
      -Durl="service:jmx:rmi:///jndi/${jndildap}/cn=x,dc=Test" \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      slp.Server &

In this command:

- The name of the agent created is `test-server-c`
- The service URL specifies the chosen connector as RMI over JRMP, and the external directory in which the RMI connector stub is stored is the LDAP server you identified as `jndildap` in Section 4.1 "Initial Configuration".
- The stub is registered in the `Test` domain component in the LDAP server.
- The common name attribute `principal` and password `credentials` are given to gain access to the LDAP server.

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the SLP service under the agent name `test-server-c`.

4. RMI connector over IIOP, without an external directory.

Start `Server` by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-d \
      -Durl="service:jmx:iiop://" \
      slp.Server &

In this command:

- The name of the agent created is `test-server-d`
- The service URL specifies the chosen connector as RMI connector over IIOP.

When the `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its automatically generated URL in the SLP service.

5. RMI connector over IIOP, using CORBA naming as the external directory.

Start `Server` by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-e \
      -Durl="service:jmx:iiop:///jndi/${jndiiiop}/server" \
      slp.Server &

In this command:

- The name of the agent created is `test-server-e`
- The service URL specifies the chosen connector as RMI connector over IIOP. The external directory in which the RMI connector stub `server` is stored is the CORBA naming service you identified as `jndiiiop` in Section 4.1 "Initial Configuration"

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the SLP service under the name `test-server-e`.

6. RMI connector over IIOP, using LDAP as the external directory.

Start `Server` by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-f \
      -Durl="service:jmx:iiop:///jndi/${jndildap}/cn=x,dc=Test" \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      slp.Server &

In this command:

- The name of the agent created is `test-server-f`
- The service URL specifies the chosen connector as RMI over IIOP, and the external directory in which the RMI connector stub is stored is the LDAP server you identified as `jndildap` in Section 4.1 "Initial Configuration".
- The stub is registered in the `Test` domain component in the LDAP server.
- The common name attribute `principal` and password `credentials` are given to gain access to the LDAP server.

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the SLP service under the agent name `test-server-f`.

2. Start the `Client`.

After starting the `Server` using the transport and external directory of your choice, start the `Client`:

    $ java -classpath .:$classp -Ddebug=true \
         -Djava.naming.security.principal="$principal" \
         -Djava.naming.security.credentials="$credentials" \
         slp.Client

You will see output confirming the detection of the agents created by the `Server` and registered in the lookup service. You will also see the identification and confirmation of the connection made to the agents.

To look up a specific agent, type the following command:

    $ java -classpath .:$classp -Ddebug=true \
         -Djava.naming.security.principal="$principal" \
         -Djava.naming.security.credentials="$credentials" \
         -Dagent.name="agentName" \
        slp.Client

In the command shown above, agentName is the name of the agent you want to look up. You can also specify a partial agent name by using `*`; for example, `x*` for all agent names beginning with the letter x.

## 4.3 Jini Lookup Service

The purpose of this example is to demonstrate how a JMX technology connector client can find and connect to a connector server that has registered with the Jini lookup service. This example performs the following operations:

1. The agent:

1. Creates an MBean server
2. Creates a connector server
3. Registers the connector address with the Jini lookup service

2. The client:

1. Gets a pointer to the Jini lookup service
2. Looks for any connector servers registered in the Jini lookup service
3. Creates a JMX Remote API connector
4. Retrieves information about the MBeans in the MBean server

The Jini lookup service example is contained in the directory work_dir`/jmx_examples/Lookup/jini`.

Note – These examples assume that you are already familiar with the Jini network technology. The documentation for the Jini network technology is available at `http://wwws.sun.com/software/jini/specs/index.html`. You can download the Jini network technology from the Sun Microsystems Community Source Licensing page, at `http://wwws.sun.com/software/communitysource/jini/download.html`. This example has been implemented using the Jini Technology Starter Kit Version 1.2.1_001.

1. Open the work_dir`/jmx_examples``/Lookup/jini` directory.

Inside this directory, you will find the following files:

- `Server.java`
- `Client.java`
- `java.policy`
- `jini.properties.template`
- `README`

2. Open each of the files in a text editor.

These classes will be analyzed in the following sections.

### 4.3.1 Analyzing the Example Classes

The following sections analyze each of the classes used in the Jini lookup service example, and explain how they perform the operations described above.

#### 4.3.1.1 Server.java

Due to its size, the Jini lookup service `Server.java` class is shown as a series of code excerpts.

CODE EXAMPLE 4-8 Jini Lookup Service Example Class Server.java (Excerpt 1)

    public class Server {
       private final MBeanServer mbs;
       private static boolean debug = false;
       public Server() {
         mbs = MBeanServerFactory.createMBeanServer();
       }

    [...]

CODE EXAMPLE 4-8 shows the creation of an MBean server `mbs`. As was the case for the SLP examples, the JMX service URL and the agent name are passed to `Server` when it is launched at the command line.

CODE EXAMPLE 4-9 Jini Lookup Service Example Class Server.java (Excerpt 2)

    [...]

       public JMXConnectorServer rmi(String url)
          throws IOException, JMException, ClassNotFoundException {
          JMXServiceURL jurl = new JMXServiceURL(url);
          final HashMap env = new HashMap();
          // Environment map attributes
         [...]
         JMXConnectorServer rmis =
            JMXConnectorServerFactory.newJMXConnectorServer(jurl, env, mbs);

         final String agentName = System.getProperty("agent.name",
                                                     "DefaultAgent");

         start(rmis,env,agentName);

         return rmis;
       }

    [...]

CODE EXAMPLE 4-9 shows the creation of an RMI connector server named `rmis`, using the system properties defined by the environment map `env` and the address `jurl`.

The RMI connector server `rmis` is started. The RMI connector server address is registered in the Jini lookup service under the name `agentName`.

CODE EXAMPLE 4-10 Jini Lookup Service Example Class Server.java (Excerpt 3)

    [...]

       public void start(JMXConnectorServer server, Map env, String agentName)
          throws IOException, ClassNotFoundException {
          server.start();
          final ServiceRegistrar registrar=getRegistrar();
          final JMXConnector proxy = server.toJMXConnector(env);
          register(registrar,proxy,agentName);
       }

       public static ServiceRegistrar getRegistrar()
          throws IOException, ClassNotFoundException,
             MalformedURLException {
          final String jurl =
             System.getProperty("jini.lookup.url","jini://localhost");
          final LookupLocator lookup = new LookupLocator(jurl);
          final ServiceRegistrar registrar = lookup.getRegistrar();
          if (registrar instanceof Administrable)
              debug("Registry is administrable.");
          return registrar;
       }

       public static ServiceRegistration register(ServiceRegistrar registrar,
                                                  JMXConnector proxy, String name)
          throws IOException {
          Entry[] serviceAttrs = new Entry[] {
                  new net.jini.lookup.entry.Name(name)
                           };

          System.out.println("Registering proxy: AgentName=" + name );
          debug("" + proxy);
          ServiceItem srvcItem = new ServiceItem(null, proxy, serviceAttrs);
          ServiceRegistration srvcRegistration =
                 registrar.register(srvcItem, Lease.ANY);
          debug("Registered ServiceID: " +
                                  srvcRegistration.getServiceID().toString());
          return srvcRegistration;
       }

    [...]

CODE EXAMPLE 4-10 shows the creation of a connector server named `server` with the environment map `env` and the service URL `jurl`. The connector server instance server then gets a pointer to the Jini lookup service by calling the Jini lookup service method `LookupLocator.getRegistrar()`.

The connector server is registered in the Jini lookup service in the form of a proxy, using the Jini lookup service locator `registrar` and the agent name under which the connector server will be registered. The proxy is in fact a client stub for the connector server, obtained by a call to the `toJMXConnector()` method of `JMXConnectorServer`.

The registration itself is performed by a call to the `register()` method of the Jini lookup service class `ServiceRegistrar`, with an array of service items.

#### 4.3.1.2 Client.java

The Jini lookup service example class `Client.java` is shown in CODE EXAMPLE 4-11.

CODE EXAMPLE 4-11 Jini Lookup Service Example Class Client.java

    public class Client {

       private static boolean debug = false;
       public static ServiceRegistrar getRegistrar()
           throws IOException, ClassNotFoundException, MalformedURLException {
           final String jurl =
                      System.getProperty("jini.lookup.url","jini://localhost");
           final LookupLocator lookup = new LookupLocator(jurl);
           final ServiceRegistrar registrar = lookup.getRegistrar();
           if (registrar instanceof Administrable)
                   debug("Registry is administrable.");
           return registrar;
     }

       public static List lookup(ServiceRegistrar registrar,
               String name) throws IOException {
           final ArrayList list = new ArrayList();
           final Class[] classes = new Class[] {JMXConnector.class};
           final Entry[] serviceAttrs = new Entry[] {
               new net.jini.lookup.entry.Name(name)
       };

       ServiceTemplate template =
            new ServiceTemplate(null,classes,serviceAttrs);
       ServiceMatches matches =
            registrar.lookup(template, Integer.MAX_VALUE);
       for(int i = 0; i < matches.totalMatches; i++) {
            debug("Found Service: " + matches.items[i].serviceID);
            if (debug) {
               if (matches.items[i].attributeSets != null) {
                       final Entry[] attrs = matches.items[i].attributeSets;
                       for (int j = 0; j < attrs.length ; j++) {
                           debug("Attribute["+j+"]=" + attrs[j]);
                   }
               }
            }

            if(matches.items[i].service != null) {
                JMXConnector c = (JMXConnector)(matches.items[i].service);
                debug("Found a JMXConnector: " + c);
                list.add(c);
            }
       }
       return list;
    }

    [...]

CODE EXAMPLE 4-11 shows how the connector client obtains a pointer to the Jini lookup service with a call to `lookup.getRegistrar()`. The client then obtains the list of the connectors registered as entries in the Jini lookup service with the agent name `name`. Unlike in the SLP example, the agent name you pass to `Client` when it is launched must be either an exact match of an existing agent name, or null, in which case the Jini lookup service will look up all the agents.

Once the list of connectors has been obtained, in code that is not shown here, the client connects to the MBean server started by `Server`, and retrieves the list of all the MBeans registered in it.

#### 4.3.1.3 java.policy

The `java.policy` file is a Java technology security policy file, configured for this example.

#### 4.3.1.4 jini.properties.template

A template Jini networking techology properties file, to be configured for this example. Change @INSTALL_HOME_FOR_JINI@ and rename the file to `jini.properties`.

### 4.3.2 Running the Jini Lookup Service Example

In addition to the actions you performed in Section 4.1 "Initial Configuration", before you can run the lookup service examples that use the Jini lookup service, you must perform some further initial actions that are specific to this example. You can then start looking up connectors using the Jini network technology, in conjunction with the connector supported by the JMX technology.

When you run the examples, to help you keep track of which agent has been created with which transport, the agent names include a letter suffix that is the same as the lettering of the corresponding section. For example, the agent from Section a. "RMI connector over JRMP, without an external directory." is called `test-server-a`.

#### 4.3.2.1 Setting up the Jini Lookup Service Example

The following steps are required by all of the different transports you can run in this example.

1. For your convenience when compiling and running the example classes, define some additional environment variables.

In addition to the common environment variables that you set in Section 4.1 "Initial Configuration" you can add the path to the Jini lookup service. The directory where you have installed the Jini networking technology is referred to as jini_dir.

`$` JINI_HOME=jini_dir

`$` JINILIB=$JINI_HOME/lib

2. Define the `classp` environment variable.

This example requires the JAR files for the Jini lookup services core and extensions.

`$` classp=$JINILIB/jini-core.jar:$JINILIB/jini-ext.jar

3. Create a `jini.properties` file.

A properties file for UNIX platforms is provided in the same directory as the classes for this example. If you are not running a UNIX platform, you can obtain a properties file for your platform in the following directory:

$JINI_HOME/example/launcher/jini12_<platform>.properties

4. Update the `jini.properties` file.

You must complete the file to include all the necessary paths, host names and port numbers for your system. Even if you are not running a UNIX platform, you can use the template provided as a guide.

5. Start the Jini networking technology `StartService`.

`$` java -cp $JINILIB/jini-examples.jar com.sun.jini.example.launcher.StartService &

This will open the `StartService` graphical user interface.

6. Load your `jini.properties` file into `StartService`.

Click on ‘File’, ‘Open Property File’ and then select your properties file from within work_dir`/jmx_examples`/Lookup/jini.

7. Start the Jini lookup services.

Start the required Jini lookup services by clicking on the ‘Run’ tab and then pressing the ‘START’ button for each of the following:

- RMID
- WebServer
- Reggie
- LookupBrowser

You will see confirmation that the services are running.

8. Compile the `Client` and `Server` classes.

Type the following command:

`$` javac -d . -classpath $classp Server.java Client.java

#### 4.3.2.2 Running the Jini Lookup Service Example

This example demonstrates the use of the Jini lookup service to look up RMI connector servers that use RMI’s default transport, JRMP, as well as the IIOP transport. In addition, as described in Section 4.1 "Initial Configuration", different external directories are used to register the RMI connector stubs.

The combinations of transports and external directories demonstrated here are:

- RMI connector over the JRMP transport, with:

- No external directory
- An RMI registry
- An LDAP registry

- RMI connector over the IIOP transport, with:

- No external directory
- A CORBA naming service
- An LDAP registry

1. Start the `Server`.

The command you use to start the `Server` varies according to which external directory you are using. You can start one or more of the following instances of `Server` with different transports and external registries before starting the `Client`.

1. RMI connector over JRMP, without an external directory.

Start Server by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-a \
      -Durl="service:jmx:rmi://" \
      -Djava.security.policy=java.policy \
      jini.Server &

In this command:

- `debug` is set to `true` to provide more complete screen output when the `Server` runs.
- The security policy is provided, to allow access to the Jini lookup service.
- The name of the agent to be created is `test-server-a`.
- The service URL specifies that the chosen connector is an RMI connector, running over the RMI default transport JRMP.

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the Jini lookup service.

2. RMI connector over JRMP, using an RMI registry as an external directory.

Start Server by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-b \
      -Durl="service:jmx:rmi:///jndi/${jndirmi}/server" \
      -Djava.security.policy=java.policy \
      jini.Server &

In this command:

- The security policy is provided, to allow access to the Jini lookup service.
- The name of the agent created is `test-server-b`.
- The service URL specifies the chosen connector as RMI over JRMP, and the external directory in which the RMI connector stub, `server`, is stored is the RMI registry you identified as `jndirmi` in Section 4.1 "Initial Configuration".

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the Jini lookup service.

3. RMI connector over JRMP, using LDAP as the external directory.

Start `Server` by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-c \
      -Durl="service:jmx:rmi:///jndi/${jndildap}/cn=x,dc=Test" \
      -Djava.security.policy=java.policy \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      jini.Server &

In this command:

- The security policy is provided, to allow access to the Jini lookup service.
- The name of the agent created is `test-server-c`.The service URL specifies the chosen connector as RMI over JRMP, and the external directory in which the RMI connector stub is stored is the LDAP server you identified as `jndildap` in Section 4.1 "Initial Configuration".
- The stub is registered in the `Test` domain component in the LDAP server.
- The common name attribute `principal` and password `credentials` are given to gain access to the LDAP server.

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the Jini lookup service under the agent name `test-server-c`.

4. RMI connector over IIOP, without an external directory.

Start `Server` by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-d \
      -Durl="service:jmx:iiop://" \
      -Djava.security.policy=java.policy \
      jini.Server &

In this command:

- The security policy is provided, to allow access to the Jini lookup service
- The name of the agent created is `test-server-d`
- The service URL specifies the chosen connector as RMI connector over IIOP.

When the `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its automatically generated URL in the Jini lookup service.

5. RMI connector over IIOP, using CORBA naming as the external directory.

Start `Server` by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-e \
      -Durl="service:jmx:iiop:///jndi/${jndiiiop}/server" \
      -Djava.security.policy=java.policy \
      jini.Server &

In this command:

- The security policy is provided, to allow access to the Jini lookup service.
- The name of the agent created is `test-server-e`.
- The service URL specifies the chosen connector as RMI connector over IIOP. The external directory in which the RMI connector stub, `server`, is stored is the CORBA naming service you identified as `jndiiiop` in Section 4.1 "Initial Configuration".

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the Jini lookup service under the name `test-server-e`.

6. RMI connector over IIOP, using LDAP as the external directory.

Start Server by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Dagent.name=test-server-f \
      -Durl="service:jmx:iiop:///jndi/${jndildap}/cn=x,dc=Test" \
      -Djava.security.policy=java.policy \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      jini.Server &

In this command:

- The security policy is provided, to allow access to the Jini lookup service.
- The name of the agent created is `test-server-f`.
- The service URL specifies the chosen connector as RMI over IIOP.
- The external directory in which the RMI connector stub is stored is the LDAP server you identified as `jndildap` in Section 4.1 "Initial Configuration".
- The stub is registered in the `Test` domain component in the LDAP server.
- The common name attribute `principal` and password `credentials` are given to gain access to the LDAP server.

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the Jini lookup service under the agent name `test-server-f`.

2. Start the `Client`.

After starting the `Server` using the transport and external directory of your choice, start the `Client`:

    $ java -classpath .:$classp -Ddebug=true \
      -Djava.security.policy=java.policy \
      jini.Client

You will see output confirming the detection of the agents created by the `Server` and registered in the lookup service. You will also see the identification and confirmation of the connection made to the agents.

To look up a specific agent, you can do so by typing the following command:

    $ java -classpath .:$classp -Ddebug=true \
      -Djava.security.policy=java.policy \
      -Dagent.name=agentName \
      jini.Client

In the command shown above, agentName is the name of the agent you want to look up. You can also specify a partial agent name by using `*`; for example, `x*` for all agent names beginning with the letter `x`.

## 4.4 Java Naming and Directory Interface (JNDI) / LDAP Lookup Service

JMX technology allows you to register RMI connectors with a JNDI lookup service using an LDAP registry as a backend. This example performs the following operations:

1. The agent:

1. Creates an MBean server
2. Creates a connector server
3. Registers the connector address with the LDAP server

2. The client:

1. Gets a pointer to the JNDI/LDAP lookup Service
2. Looks for any connector servers registered in the JNDI/LDAP lookup service
3. Creates a JMX Remote API connector
4. Retrieves information about the MBeans in the MBean server

1. The JNDI/LDAP lookup example is contained in the directory work_dir`/jmx_examples/Lookup/ldap`. Open the work_dir`/jmx_examples/Lookup/ldap` directory.

Inside this directory, you will find the following files:

- `Server.java`
- `Client.java`
- `jmx-schema.txt`
- `60jmx-schema.ldif`
- `README`

2. Open the files in a text editor.

These classes will be analyzed in the following sections.

### 4.4.1 Analyzing the Example Classes

The following sections analyze each of the classes used in the JNDI/LDAP lookup service example, and explain how they perform the operations described above.

#### 4.4.1.1 Server.java

Due to its size, the JNDI/LDAP lookup service `Server.java` class is shown as a series of code excerpts.

CODE EXAMPLE 4-12 JNDI/LDAP Lookup Service Example Server.java (Excerpt 1)

    [...]

    public class Server {
       public final static int JMX_DEFAULT_LEASE = 60;
       private static boolean debug = false;
       private final MBeanServer mbs;
       public Server() {
          mbs = MBeanServerFactory.createMBeanServer();
       }

      public static DirContext getRootContext() throws NamingException {
          final Hashtable env = new Hashtable();

          final String factory =
            System.getProperty(Context.INITIAL_CONTEXT_FACTORY,
                               "com.sun.jndi.ldap.LdapCtxFactory");
          final String ldapServerUrl =
            System.getProperty(Context.PROVIDER_URL);
          final String ldapUser =
            System.getProperty(Context.SECURITY_PRINCIPAL,
                               "cn=Directory Manager");
          final String ldapPasswd =
            System.getProperty(Context.SECURITY_CREDENTIALS);
          debug(Context.PROVIDER_URL + "=" + ldapServerUrl);
          debug(Context.SECURITY_PRINCIPAL + "=" + ldapUser);
          if (debug) {
                      System.out.print(Context.SECURITY_CREDENTIALS + "=");
                      final int len = (ldapPasswd==null)?0:ldapPasswd.length();
                      for (int i=0;i<len;i++) System.out.print("*");
                      System.out.println();
          }
          env.put(Context.INITIAL_CONTEXT_FACTORY,factory);
          env.put(Context.SECURITY_PRINCIPAL, ldapUser);
          if (ldapServerUrl != null)
               env.put(Context.PROVIDER_URL, ldapServerUrl);
          if (ldapPasswd != null)
               env.put(Context.SECURITY_CREDENTIALS, ldapPasswd);
          InitialContext root = new InitialLdapContext(env,null);
          return (DirContext)(root.lookup(""));
      }

    [...]

CODE EXAMPLE 4-12 shows the initial creation of an MBean server `mbs`, and the obtention of a pointer to the root context of the LDAP directory tree in which the connector server address is to be registered. All the relevant LDAP access variables, such as the provider URL, the LDAP user name and the security credentials, are given here and passed into the environment map `env`. The environment map `env` is then passed as a parameter into a call to `InitialLdapContext`, from which the initial LDAP context is obtained.

Code that is omitted from CODE EXAMPLE 4-12 retrieves the agent name under which the connector will be registered in the LDAP server.

CODE EXAMPLE 4-13 JNDI/LDAP Lookup Service Example Server.java (Excerpt 2)

    [...]

    public static void register(DirContext root,
                               JMXServiceURL jmxUrl,
                               String name)
       throws NamingException, IOException {

       final String mydn = System.getProperty("dn","cn="+name);

       debug("dn: " + mydn );

       Object o = null;
       try {
           o = root.lookup(mydn);
       } catch (NameNotFoundException n) {
           Attributes attrs = new BasicAttributes();
           Attribute objclass = new BasicAttribute("objectClass");
           objclass.add("top");
           objclass.add("javaContainer");
           objclass.add("jmxConnector");
           attrs.put(objclass);
           attrs.put("jmxAgentName", name);
           o = root.createSubcontext(mydn,attrs);
       }
       if (o == null) throw new NameNotFoundException();
       final Attributes attrs = root.getAttributes(mydn);
       final Attribute oc = attrs.get("objectClass");
       if (!oc.contains("jmxConnector")) {
           final String msg = "The supplied node [" + mydn +
             "] does not contain the jmxConnector objectclass";
           throw new NamingException(msg);
       }

       final Attributes newattrs = new BasicAttributes();
       newattrs.put("jmxAgentName",name);
       newattrs.put("jmxServiceURL",jmxUrl.toString());
       newattrs.put("jmxAgentHost",InetAddress.getLocalHost().getHostName());
       newattrs.put("jmxProtocolType",jmxUrl.getProtocol());
       newattrs.put("jmxExpirationDate",
                    getExpirationDate(JMX_DEFAULT_LEASE));
       root.modifyAttributes(mydn,DirContext.REPLACE_ATTRIBUTE,newattrs);
    }

    [...]

CODE EXAMPLE 4-13 shows the registration of JMX connector server service URL in the LDAP directory. The DN where the URL will be registered can be passed on the command line through the `dn` System property, that is, `-Ddn=`mydn (see later the commands used start the server). If the `dn` System property is not specified, then you can use the DN: `cn=`name where name is the `agentName`. Naturally, this is not mandatory. The location where the URL is registered does not really matter, because the client code never uses that DN directly, but instead performs an LDAP search to find the nodes which have an auxiliary `jmxConnector` `ObjectClass`. What is important here is that each URL is registered in its own LDAP node. How to name these nodes is left to the LDAP administrator, who in this case is you. In this example, it is assumed that you have configured your LDAP server by creating a `root` context under which the node `cn=`name can be created, and that this `root` context has been passed to the LDAP initial context through the `Context.PROVIDER_URL` property (see CODE EXAMPLE 4-12).

The code shown in CODE EXAMPLE 4-13 checks whether the node in which you will register the server URL already exists. If it does not, you try to create it (this will fail if the parent node does not exist). Since the `jmxConnector` `ObjectClass` is a simple auxiliary class, you will use the `javaContainer ObjectClass` as structural class if you need to create a new context. Once again, this is completely optional. Any structural class to which the `jmxConnector` auxiliary class could be added would be acceptable. It then checks whether the node in which you will register the server already has the `jmxConnector` auxiliary class. If not, an exception is thrown.

At this point you are sure that the node in which you will register the URL exists, and has the appropriate `jmxConnector` auxiliary class. So you need only to replace the values of the attributes defined by JMX Remote API for LDAP lookup (see `jmx-schema.txt`):

- `jmxServiceUrl`: contains the `String` form of the server URL, as obtained from `server.getAddress()` after the server was started
- `jmxAgentName`: contains the JMX agent name
- `jmxProtocolType`: contains the JMX protocol type, as returned by `jmxUrl.getProtocolType()`
- `jmxAgentHost`: contains the name of the agent host
- `jmxExpirationDate`: contains the date at which the URL will be considered obsolete.

CODE EXAMPLE 4-14 JNDI/LDAP Lookup Service Example Server.java (Excerpt 3)

    [...]

       public JMXConnectorServer rmi(String url)
         throws IOException, JMException,
            NamingException, ClassNotFoundException {

         JMXServiceURL jurl = new JMXServiceURL(url);
         final HashMap env = new HashMap();
         // Prepare the environment Map

    [...]

         JMXConnectorServer rmis =
            JMXConnectorServerFactory.newJMXConnectorServer(jurl, env, mbs);

         final String agentName = System.getProperty("agent.name",
                                                     "DefaultAgent");
         start(rmis,env,agentName);
         return rmis;
       }

    [...]

In CODE EXAMPLE 4-14, a new RMI connector server named `rmis` is created with the JMX service URL `jurl` and the appropriate LDAP properties passed to its environment map `env`. The connector server `rmis` is launched by calling `JMXConnectorServer.start()` and is registered in the LDAP server.

CODE EXAMPLE 4-15 JNDI/LDAP Lookup Service Example Server.java (Excerpt 4)

    [...]

        public void start(JMXConnectorServer server, Map env, String agentName)
           throws IOException, NamingException {
           server.start();
           final DirContext root=getRootContext();
           final JMXServiceURL address = server.getAddress();
           register(root,address,agentName);
        }

    [...]

CODE EXAMPLE 4-15 shows the creation of a JMX connector server `server`, the obtention of a pointer to the LDAP server root directory `root` and the creation of a URL for `server` named `address`. The root directory, the URL and an agent name are passed as parameters to `register()` and are registered in the LDAP server.

#### 4.4.1.2 Client.java

The JNDI/LDAP lookup service `Client.java` class is shown in CODE EXAMPLE 4-16.

CODE EXAMPLE 4-16 JNDI/LDAP Lookup Service Example Client.java

    [...]

    public class Client {

       private static boolean debug = false;

       public static void listAttributes(DirContext root, String dn)
         throws NamingException {
         final Attributes attrs = root.getAttributes(dn);
         System.out.println("dn: " + dn);
         System.out.println("attributes: " + attrs);
       }

       public static DirContext getRootContext() throws NamingException {
          final Hashtable env = new Hashtable();
          // Prepare environment map
          [...]

          InitialContext root = new InitialLdapContext(env,null);
          return (DirContext)(root.lookup(""));
       }

       // Confirm URL has not expired
      [...]

       public static List lookup(DirContext root, String protocolType,
                                 String name)
          throws IOException, NamingException {
          final ArrayList list = new ArrayList();
          String queryProtocol =
             (protocolType==null)?"":"(jmxProtocolType="+protocolType+")";
          String query =
              "(&" + "(objectClass=jmxConnector) " +
              "(jmxServiceURL=*) " +
              queryProtocol +
              "(jmxAgentName=" + ((name!=null)?name:"*") + "))";

          SearchControls ctrls = new SearchControls();
          ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
          final NamingEnumeration results = root.search("", query, ctrls);
          while (results.hasMore()) {
               final SearchResult r = (SearchResult) results.nextElement();
               debug("Found node: " + r.getName());
               final Attributes attrs = r.getAttributes();
               final Attribute attr = attrs.get("jmxServiceURL");
               if (attr == null) continue;
               final Attribute exp = attrs.get("jmxExpirationDate");
               if ((exp != null) && hasExpired((String)exp.get())) {
                   System.out.print(r.getName() + ": ");
                   System.out.println("URL expired since: " + exp.get());
                   continue;
               }
               final String urlStr = (String)attr.get();
               if (urlStr.length() == 0) continue;

               debug("Found URL: "+ urlStr);

               final JMXServiceURL url = new JMXServiceURL(urlStr);
               final JMXConnector conn =
                   JMXConnectorFactory.newJMXConnector(url,null);
               list.add(conn);
               if (debug) listAttributes(root,r.getName());
          }

          return list;

       }
    }

In CODE EXAMPLE 4-16, the `Client` firstly returns a pointer `root` to the LDAP directory `DirContext`, then it searches through the directory for object classes of the type `jmxConnector`. The service URL and expiry date attributes, `attr` and `exp` respectively, for the `jmxConnector` object classes are obtained, `exp` is checked to make sure that the URL has not expired and a call is made to `JMXConnectorFactory` to create a new connector `conn`. The connector `conn` is added to the list of connectors and is used to access the MBeans in the MBean server created by `Server`.

#### 4.4.1.3 jmx-schema.txt

The `jmx-schema.txt` file is the LDAP schema file for the JMX Remote API.

#### 4.4.1.4 60jmx-schema.ldif

The `60jmx-schema.ldif` file is an `ldif` file corresponding to the LDAP schema file, `jmx-schema.txt`, for JMX technology. If you are using Sun ONE Directory Server, this file can be copied directly to the `config/schema` directory of the Sun ONE Directory Server (see Section 4.4.2.1 "Setting up the JNDI/LDAP Lookup Service Example").

### 4.4.2 Running the JNDI/LDAP Lookup Service Example

In addition to the actions you performed in Section 4.1 "Initial Configuration", before you can run the lookup service examples that use the JNDI/LDAP lookup service, you must perform some further initial actions that are specific to this example. You can then start looking up connectors using the JNDI/LDAP network technology, in conjunction with the two connectors supported by the JMX technology.

When you run the examples, to help you keep track of which agent has been created with which transport, the agent names include a letter suffix that is the same as the lettering of the corresponding section. For example, the agent from Section a. "RMI connector over JRMP, without an external directory." is called `test-server-a`.

#### 4.4.2.1 Setting up the JNDI/LDAP Lookup Service Example

The following steps are required by all of the different connector/transport combinations you can run in this example.

1. Stop the LDAP server you started in Section 4.1 "Initial Configuration".

Do this according to the type of LDAP server you are using.

2. Copy the JMX technology schema into your LDAP server’s `schema` directory.

For example, if you are using Sun ONE Directory Server 5.0, you would type:

`$` cp 60jmx-schema.ldif /var/ds5/slapd-<hostname>/config/schema

Otherwise, do this according to the type of LDAP server you are using.

3. Restart the LDAP server.

Do this according to the type of LDAP server you are using.

4. Define the root under which the `Server` will register its service URL.

You must provide the `Server` with the path to the domain component suffix `dc=Test` that you created in Section 4.1 "Initial Configuration".

`$` provider="ldap://$ldaphost:$ldapport/dc=Test"

5. Compile the `Client` and `Server` classes.

`$` javac -d . Server.java Client.java

#### 4.4.2.2 Running the JNDI/LDAP Lookup Service Example With an RMI Connector

This example demonstrates the use of the JNDI/LDAP lookup service to look up RMI connector servers that use RMI’s default transport, JRMP, as well as the IIOP transport. In addition, as described in Section 4.1 "Initial Configuration", different external directories are used to register the RMI connector stubs.

The combinations of transports and external directories demonstrated here are:

- RMI connector over the JRMP transport, with:

- No external directory
- An RMI registry
- An LDAP registry

- RMI connector over the IIOP transport, with:

- No external directory
- A CORBA naming service
- An LDAP registry

1. Start the `Server`.

The command you use to start the `Server` varies according to which external directory you are using. You can start one or more of the following instances of `Server` with different transports and external registries before starting the `Client`.

1. RMI connector over JRMP, without an external directory.

Start `Server` by typing the following command:

    $ java -classpath . -Ddebug=true \
      -Dagent.name=test-server-a \
      -Durl="service:jmx:rmi://" \
      -Djava.naming.provider.url="$provider" \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      jndi.Server &

In this command:

- `debug` is set to true to provide more complete screen output when the `Server` runs.
- The name of the agent to be created is `test-server-a`.
- The URL, `provider`, that points to the domain component suffix in which the agent will be registered, is given.
- The common name attribute `principal` and password `credentials` are given to gain access to the LDAP server.
- The service URL specifies that the chosen connector is an RMI connector, running over the RMI default transport JRMP.

When Server is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the JNDI/LDAP lookup service.

2. RMI connector over JRMP, using an RMI registry as an external directory.

Start `Server` by typing the following command:

    $ java -classpath . -Ddebug=true \
      -Dagent.name=test-server-b \
      -Durl="service:jmx:rmi:///jndi/${jndirmi}/server" \
      -Djava.naming.provider.url="$provider" \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      jndi.Server &

In this command:

- The name of the agent created is `test-server-b`.
- The URL, `provider`, that points to the domain component suffix in which the agent will be registered, is given.
- The common name attribute `principal` and password `credentials` are given to gain access to the LDAP server.
- The service URL specifies the chosen connector as RMI over JRMP, and the external directory in which the RMI connector stub, `server`, is stored is the RMI registry you identified as `jndirmi` in Section 4.1 "Initial Configuration".

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the JNDI/LDAP lookup service.

3. RMI connector over JRMP, using LDAP as the external directory.

Start `Server` by typing the following command:

    $ java -classpath . -Ddebug=true \
      -Dagent.name=test-server-c \
      -Durl="service:jmx:rmi:///jndi/${jndildap}/cn=x,dc=Test" \
      -Djava.naming.provider.url="$provider" \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      jndi.Server &

In this command:

- The name of the agent created is `test-server-c`.
- The URL, `provider`, that points to the domain component suffix in which the agent will be registered, is given.
- The common name attribute `principal` and password `credentials` are given to gain access to the LDAP server.
- The service URL specifies the chosen connector as RMI over JRMP, and the external directory in which the RMI connector stub is stored is the LDAP server you identified as `jndildap` in Section 4.1 "Initial Configuration".

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the JNDI/LDAP lookup service under the agent name `test-server-c`.

4. RMI connector over IIOP, without an external directory.

Start `Server` by typing the following command:

    $ java -classpath . -Ddebug=true \
      -Dagent.name=test-server-d \
      -Durl="service:jmx:iiop://" \
      -Djava.naming.provider.url="$provider" \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      jndi.Server &

In this command:

- The name of the agent created is `test-server-d`.
- The URL, `provider`, that points to the domain component suffix in which the agent will be registered, is given.
- The common name attribute `principal` and password `credentials` are given to gain access to the LDAP server.
- The service URL specifies that the chosen connector is an RMI connector, running over IIOP.

When the `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its automatically generated URL in the JNDI/LDAP lookup service.

5. RMI connector over IIOP, using CORBA naming as the external directory.

Start `Server` by typing the following command:

    $ java -classpath . -Ddebug=true \
      -Dagent.name=test-server-e \
      -Durl="service:jmx:iiop:///jndi/${jndiiiop}/server" \
      -Djava.naming.provider.url="$provider" \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      jndi.Server &

In this command:

- The name of the agent created is `test-server-e`.
- The URL, `provider`, that points to the domain component suffix in which the agent will be registered, is given.
- The common name attribute `principal` and password `credentials` are given to gain access to the LDAP server.
- The service URL specifies the chosen connector as RMI connector over IIOP, and the external directory in which the RMI connector stub, server, is stored is the CORBA naming service you identified as `jndiiiop` in Section 4.1 "Initial Configuration".

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the JNDI/LDAP lookup service under the name `test-server-e`.

6. RMI connector over IIOP, using LDAP as the external directory.

Start `Server` by typing the following command:

    $ java -classpath . -Ddebug=true \
      -Dagent.name=test-server-f \
      -Durl="service:jmx:iiop:///jndi/${jndildap}/cn=x,dc=Test" \
      -Djava.naming.provider.url="$provider" \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      jndi.Server &

In this command:

- The name of the agent created is `test-server-f`.
- The URL, `provider`, that points to the domain component suffix in which the agent will be registered, is given.
- The common name attribute `principal` and password `credentials` are given to gain access to the LDAP server.
- The service URL specifies the chosen connector as RMI over IIOP, and the external directory in which the RMI connector stub is stored is the LDAP server you identified as `jndildap` in Section 4.1 "Initial Configuration".

When `Server` is launched, you will see confirmation of the creation of the RMI connector, and the registration of its URL in the JNDI/LDAP lookup service under the agent name `test-server-f`.

2. Start the `Client`.

After starting the `Server` using the transport and external directory of your choice, start the `Client`:

    $ java -classpath . -Ddebug=true \
      -Djava.naming.provider.url="$provider" \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      jndi.Client

You will see output confirming the detection of the agents created by the `Server` and registered in the lookup service. You will also see the identification and confirmation of the connection made to the agents.

To look up a specific agent, type the following command:

    $ java -classpath . -Ddebug=true \
      -Djava.naming.provider.url="$provider" \
      -Djava.naming.security.principal="$principal" \
      -Djava.naming.security.credentials="$credentials" \
      -Dagent.name=agentName \
      jndi.Client

In the command shown above, agentName is the name of the agent you want to look up. You can also specify a partial agent name by using *; for example, x* for all agent names beginning with the letter x.

Contents | Previous | Next | Java Management Extensions (JMX) Technology Tutorial Java Management Extensions (JMX), Java 2 Platform, Standard Edition 5.0

Copyright © 2004 Sun Microsystems, Inc. All rights reserved.