The LiveTribe :: SLP Module

How to use SLP to advertise JMXConnectorServers

In this example, based on J2SE 5, you will see how SLP can simplify the task of connecting to a remote JMXConnectorServer from a client. We will expose the J2SE 5 platform MBeanServer using an RMI JMXConnectorServer, so that clients can use an RMI JMXConnector to connect to it.

The example shows the differences between a non-SLP environment where knowledge of the location of the services is needed, and an SLP environment, where SLP takes care of discovering the location of the services.

The non-SLP environment

In the usual environment there are 3 participants:

  • The server host, that runs the MBeanServer and the JMXConnectorServer.
  • The naming host, that runs the naming server; when using the RMIRegistry, the naming host and the server host coincide.
  • The client host, that runs the JMXConnector and the client code.

The JMXConnectorServer is started with a JMXServiceURL similar to this one:

service:jmx:rmi:///jndi/rmi://naminghost/foo

where "foo" is the JNDI name under which the RMI stub is registered.

The client code must know the same JMXServiceURL, or otherwise it has no clue on how to connect to the server host. Potentially, the naming host could be any host in the network, and the server code may have registered the stub under any JNDI name, and the client may not know neither the naming host nor the JNDI name.

Often, this knowledge of the location of the services (in this case the JMX stub) is not known a priori, or it must be configured in the clients.

The SLP environment

In the SLP environment there are only 2 participants:

  • The server host, that runs the MBeanServer and the JMXConnectorServer.
  • The client host, that runs the JMXConnector and the client code.

There is no need of the naming host, nor of the RMIRegistry.

In the SLP environment, the JMXConnectorServer is started with a JMXServiceURL similar to this one:

service:jmx:rmi:///

After the JMXConnectorServer has been started, the JMXServiceURL is modified by the JMXConnectorServer, and becomes similar to this one:

service:jmx:rmi:///stub/<Base64 encoded stub>

Once the JMXConnectorServer has been started, an SLP ServiceAgent advertises the JMXServiceURL as a service. In this way, SLP UserAgents can find the advertised service and connect to it.

Below you can find examples of server and client code.

public class ExampleServer
{
  public static void main(String[] args) throws Exception
  {
    // Get the platform MBeanServer
    MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();

    // Attach a JMXConnectorServer to the platform MBeanServer
    JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi:///");
    JMXConnectorServer connectorServer = 
            JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, null, mbeanServer);
    connectorServer.start();

    // Refresh the JMXServiceURL after the JMXConnectorServer has started
    jmxServiceURL = connectorServer.getAddress();

    // Now advertise the JMXConnectorServer service via SLP

    // Convert JMXServiceURL (JMX) to ServiceURL (SLP)
    ServiceURL serviceURL = new ServiceURL(jmxServiceURL.toString());
    String language = Locale.ENGLISH.getLanguage();
    Scopes scopes = Scopes.DEFAULT;
    Attributes attributes = Attributes.NONE;
    ServiceInfo serviceInfo = new ServiceInfo(serviceURL, language, scopes, attributes);

    // Allow this code to be run by non-root users on Linux/Unix
    Settings settings = new MapSettings();
    settings.put(Keys.PORT_KEY, 4427);
    // Create the SLP ServiceAgent that advertises the JMX service
    ServiceAgent serviceAgent = SLP.newServiceAgent(settings);
    // Register the service and start the SLP ServiceAgent
    serviceAgent.register(serviceInfo);
    serviceAgent.start();

    System.out.println("Server up and running");
  }
}

public class ExampleClient
{
  public static void main(String[] args) throws Exception
  {
    // Discover the JMX services using SLP

    // Allow this code to be run by non-root users on Linux/Unix
    Settings settings = new MapSettings();
    settings.put(Keys.PORT_KEY, 4427);
    // Create the SLP UserAgentClient that discovers services
    UserAgentClient userAgentClient = SLP.newUserAgentClient(settings);

    // We're interested in JMX services of type "service:jmx"
    ServiceType serviceType = new ServiceType("service:jmx");
    // Find the services
    List<ServiceInfo> serviceInfos = userAgentClient.findServices(serviceType, null, null, null);

    // Assume there is one result
    ServiceInfo serviceInfo = serviceInfos.get(0);
    ServiceURL serviceURL = serviceInfo.getServiceURL();

    // Convert ServiceURL (SLP) to JMXServiceURL (JMX)
    JMXServiceURL jmxServiceURL = new JMXServiceURL(serviceURL.toString());
    // Create to the JMXConnector
    JMXConnector connector = JMXConnectorFactory.newJMXConnector(jmxServiceURL, null);

    try
    {
      // Connect to the JMXConnectorServer
      connector.connect();

      // Call the server to be sure we're connected properly
      MBeanServerConnection connection = connector.getMBeanServerConnection();
      ObjectName delegate = ObjectName.getInstance("JMImplementation:type=MBeanServerDelegate");
      String result = (String)connection.getAttribute(delegate, "ImplementationVendor");

      System.out.println("JMX implementor = " + result);
    }
    finally
    {
      connector.close();
    }
  }
}