Chapter 12: Discovery Management

This chapter discusses some utility classes that make it easier to deal with lookup services.

12.1. Management Interfaces

Both services and clients need to find lookup locators. Services will register with these locators, and clients will query them for suitable services. Finding these lookup locators involves three components:

  1. A list of LookupLocators for unicast discovery

  2. A list of groups for lookup locators using multicast discovery

  3. Listeners whose methods are invoked when a service locator is found

The chapter "Discovering a Lookup Service" considered the cases of a single unicast lookup service, or a set of multicast lookup services. There are also mechanisms to handle a set of unicast lookup services and a set of multicast lookup services. There are three interfaces involved in this

  1. DiscoveryManagement which looks after discovery events

  2. DiscoveryGroupManagement which looks after groups and multicast search

  3. DiscoveryLocatorManagement which looks after unicast discovery

Different classes may implement different combinations of these three interfaces. The class LookupDiscovery discussed in chapter three uses DiscoveryGroupManagement and DiscoveryManagement. This performs multicast search, informing its listeners when lookup services are discovered. The class LookupLocatorDiscovery is discussed later in this chapter. It performs a similar task for unicast discovery. It implements the two interfaces DiscoveryLocatorManagement and DiscoveryManagement. Another class discussed later is LookupDiscoveryManager which handles both unicast and broadcast discovery, and so implements all three interfaces. With these three cases covered, it is unlikely that you will need to implement these interfaces yourself.

The DiscoveryManagement interface is


package net.jini.discovery;

public interface DiscoveryManagement { 
    public void addDiscoveryListener(DiscoveryListener l);
    public void removeDiscoveryListener(DiscoveryListener l);
    public ServiceRegistrar[] getRegistrars();
    public void discard(ServiceRegistrar proxy);
    public void terminate();  
}
The method addDiscoveryListener() is the most important of these, as it allows a listener object to be informed whenever a new lookup service is discovered.

The DiscoveryGroupManagement interface is


package net.jini.discovery;
  
public interface DiscoveryGroupManagement {
 
    public static final String[] ALL_GROUPS = null;
    public static final String[] NO_GROUPS = new String[0];
 
    public String[] getGroups();
    public void addGroups(String[] groups) throws IOException;
    public void setGroups(String[] groups) throws IOException;
    public void removeGroups(String[] groups);
}
The most important of these is setGroups(). If the groups have initially been set to NO_GROUPS, no multicast search is performed. If it is later changed by setGroups() then this initiates search. Similarly, addGroups() will also initiate search. (This is why they may throw remote exceptions.)

The third interface is DiscoveryLocatorManagement


package net.jini.discovery;

public interface DiscoveryLocatorManagement {
    public LookupLocator[] getLocators();
    public void addLocators(LookupLocator[] locators);
    public void setLocators(LookupLocator[] locators);
    public void removeLocators(LookupLocator[] locators);
}
An implementation will generally set the locators in its own constructor, so these methods will probably only be useful if you need to change the set of unicast addresses for the lookup services.

12.2. LookupLocatorDiscovery

In the chapter on ``Discovering a Lookup Service'', the section on finding a lookup service at a known address only looked at a single address. If lookup services at multiple addresses are required, then a naive solution would be to put the code from that chapter into a loop. The LookupLocatorDiscovery class provides a more satisfactory solution by providing the same event handling method as in the multicast case: that is, you supply a list of addresses, and when a lookup service is found at one of these address, a listener object is informed.

The class is specified by


package net.jini.discovery;

public class LookupLocatorDiscovery implements DiscoveryManagement,
                                               DiscoveryLocatorManagement {
    public LookupLocatorDiscovery(LookupLocator[] locators);
    public LookupLocatorDiscovery(LookupLocator[] locators, 
                                  Configuration config);
    public LookupLocator[] getDiscoveredLocators();
    public LookupLocator[] get UndiscoveredLocators();
}
An additional constructor has been added in Jini 2.0

Rewriting the unicast example from the chapter "Discovering a Lookup Service" using this utility class makes it look much like the example on multicast discovery from the same chapter. The similarities are that it now uses the same event model for lookup service discovery, the differences are that it uses a set of LookupLocator objects rather than a set of groups.


package discoverymgt;

import net.jini.discovery.LookupLocatorDiscovery;
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.DiscoveryEvent;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.discovery.LookupLocator;
import java.net.MalformedURLException;
import java.rmi.RMISecurityManager;

/**
 * UniicastRegister.java
 */

public class UnicastRegister implements DiscoveryListener {
 
    static public void main(String argv[]) {
        new UnicastRegister();

	// stay around long enough to receive replies
	try {
	    Thread.currentThread().sleep(10000L);
	} catch(java.lang.InterruptedException e) {
	    // do nothing
	}
    }
      
    public UnicastRegister() {
	// install suitable security manager
	System.setSecurityManager(new RMISecurityManager());

        LookupLocatorDiscovery discover = null;
	LookupLocator[] locators = null;
	try {
	    locators = new LookupLocator[] {new LookupLocator("jini://localhost")};
	} catch(MalformedURLException e) {
	    e.printStackTrace();
	    System.exit(1);
	}
        try {
            discover = new LookupLocatorDiscovery(locators);
        } catch(Exception e) {
            System.err.println(e.toString());
	    e.printStackTrace();
	    System.exit(1);
        }

        discover.addDiscoveryListener(this);
    }
    
    public void discovered(DiscoveryEvent evt) {

        ServiceRegistrar[] registrars = evt.getRegistrars();

        for (int n = 0; n < registrars.length; n++) {
	    ServiceRegistrar registrar = registrars[n];

	    // the code takes separate routes from here for client or service
	    System.out.println("found a service locator");
  	}
    }

    public void discarded(DiscoveryEvent evt) {

    }
} // UnicastRegister


12.3. LookupDiscoveryManager

An application (client or service) that wants to use a set of lookup services at fixed, known addresses and also to use whatever lookup services it can find by multicast can use the utility class LookupDiscoveryManager. Most of the methods of this class come from its interfaces:


package net.jini.discovery;

public class LookupDiscoveryManager implements DiscoveryManagement,
                                               DiscoveryGroupManagement,
                                               DiscoveryLocatorManagement {
    public LookupDiscoveryManager(String[] groups,
                                  LookupLocator[] locators,
                                  DiscoveryListener listener)
                                      throws IOException;
    public LookupDiscoveryManager(String[] groups,
                                  LookupLocator[] locators,
                                  DiscoveryListener listener,
                                  Configuration config)
                                      throws IOException,
                                             ConfigurationException;
}
This differs from LookupDiscovery and LookupLocatorDiscovery in that it insists on a DiscoveryListener in its constructor. Programs using this can follow the same event model as the last example:

package discoverymgt;

import net.jini.discovery.LookupDiscoveryManager;
import net.jini.discovery.DiscoveryGroupManagement;
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.DiscoveryEvent;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.discovery.LookupLocator;
import java.net.MalformedURLException;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;

/**
 * AllcastRegister.java
 */

public class AllcastRegister implements DiscoveryListener {
 
    static public void main(String argv[]) {
        new AllcastRegister();

	// stay around long enough to receive replies
	try {
	    Thread.currentThread().sleep(10000L);
	} catch(java.lang.InterruptedException e) {
	    // do nothing
	}
    }
      
    public AllcastRegister() {
	// install suitable security manager
	System.setSecurityManager(new RMISecurityManager());

        LookupDiscoveryManager discover = null;
	LookupLocator[] locators = null;
	try {
	    locators = new LookupLocator[] {new LookupLocator("jini://localhost")};
	} catch(MalformedURLException e) {
	    e.printStackTrace();
	    System.exit(1);
	}
        try {
            discover = new LookupDiscoveryManager(DiscoveryGroupManagement.ALL_GROUPS,
						  locators,
						  this);
        } catch(IOException e) {
            System.err.println(e.toString());
	    e.printStackTrace();
	    System.exit(1);
        }
    }
    
    public void discovered(DiscoveryEvent evt) {

        ServiceRegistrar[] registrars = evt.getRegistrars();

        for (int n = 0; n < registrars.length; n++) {
	    ServiceRegistrar registrar = registrars[n];

	    try {
		System.out.println("found a service locator at " +
			       registrar.getLocator().getHost());
	    } catch(RemoteException e) {
		e.printStackTrace();
		continue;
	    }
	    // the code takes separate routes from here for client or service
  	}
    }

    public void discarded(DiscoveryEvent evt) {

    }
} // AllcastRegister


12.4. Conclusion

The LookupLocatorDiscovery and LookupDiscoveryManager add to the LookupDiscovery class by making it easier to find lookup services using both unicast and broadcast search.

12.5. Copyright

If you found this chapter of value, the full book "Foundations of Jini 2 Programming" is available from APress or Amazon .

This file is Copyright (©) 1999, 2000, 2001, 2003, 2004, 2005 by Jan Newmarch (http://jan.newmarch.name) jan@newmarch.name.

Creative Commons License This work is licensed under a Creative Commons License, the replacement for the earlier Open Content License.