Chapter 11: Join Manager

Finding a lookup service involves a common series of steps. Subequent interaction with them also involves common steps. A join manager encapulates these into one convenience class for services.

11.1. Join Manager

A service needs to locate lookup services and register the service with them. Locating services can be done using the utility classes of ``Discovery Management''. As each lookup service is discovered, it then needs to be registered, and the lease maintained. The class JoinManager performs all of these tasks. There are two constructors


public class JoinManager {
     public JoinManager(Object obj,
                        Entry[] attrSets,
                        ServiceIDListener callback,
                        DiscoveryManagement discoverMgr,
                        LeaseRenewalManager leaseMgr)    
            throws IOException;

     public JoinManager(Object obj,
                        Entry[] attrSets,
                        ServiceID serviceID,
                        DiscoveryManagement discoverMgr,
                        LeaseRenewalManager leaseMgr)    
            throws IOException;
}
The first of these is when the service is new and does not have a service id. A ServiceIDListener can be added which can note and save the id. The second form is used when the service already has an id. The other parameters are for the service and its entry attributes, a DiscoveryManagement object to set groups and unicast locators (typically this will be done using a LookupDiscoveryManager) and a lease renewal manager. The following example uses this to register a FileClassifierImpl. There is no need for a DiscoveryListener, since the join manager adds itself as a listener and handles the registration with the lookup service.

package joinmgr;

import rmi.FileClassifierImpl;

import net.jini.lookup.JoinManager;
import net.jini.core.lookup.ServiceID;
import net.jini.discovery.LookupDiscovery;
import net.jini.core.lookup.ServiceRegistrar;
import java.rmi.RemoteException;
import net.jini.lookup.ServiceIDListener;
import net.jini.lease.LeaseRenewalManager;
import net.jini.discovery.LookupDiscoveryManager;
import net.jini.discovery.DiscoveryEvent;
import net.jini.discovery.DiscoveryListener;


/**
 * FileClassifierServer.java
 */

public class FileClassifierServer 
    implements ServiceIDListener {
    
    public static void main(String argv[]) {
	new FileClassifierServer();

        // stay around forever
	Object keepAlive = new Object();
	synchronized(keepAlive) {
	    try {
		keepAlive.wait();
	    } catch(InterruptedException e) {
		// do nothing
	    }
	}
    }

    public FileClassifierServer() {

	JoinManager joinMgr = null;
	try {
	    LookupDiscoveryManager mgr = 
		new LookupDiscoveryManager(LookupDiscovery.ALL_GROUPS,
					   null /* unicast locators */,
					   null /* DiscoveryListener */);
	    joinMgr = new JoinManager(new cokeServer.CokeMachine(), // new FileClassifierImpl(), /* service */
				      null /* attr sets */,
				      this /* ServiceIDListener*/,
				      mgr /* DiscoveryManagement */,
				      new LeaseRenewalManager());
	} catch(Exception e) {
	    e.printStackTrace();
	    System.exit(1);
	}
    }

    public void serviceIDNotify(ServiceID serviceID) {
	// called as a ServiceIDListener
	// Should save the id to permanent storage
	System.out.println("got service ID " + serviceID.toString());
    }
    
} // FileClassifierServer

There are a number of other methods in JoinManager, which allow one to modify the state of a service registration.

11.2. Jini 1.0 JoinManager

A version of JoinManager was present in Jini 1.0. At that time it was in the package com.sun and no formal specification was given. Classes in the com.sun packages may be changed in later versions of Jini, or may even disappear completely. In moving from Jini 1.0 to Jini 1.1 the JoinManager classes have now been specified and moved to a new package. This section describes the old version for those still using Jini 1.0. When possible, such users should switch to Jini 1.1

There are a number of possible constructors for JoinManager. The simplest is


JoinManager(java.lang.Object obj, 
            Entry[] attrSets, 
            ServiceIDListener callback, 
            LeaseRenewalManager leaseMgr) 
This specifies the service to be managed and its entry attributes. The callback will have its serviceIDNotify() method called when a new locator is discovered. This argument can be null if the application has no interest in this. The leaseMgr can also be set to null and will then be created as needed.

Using this constructor will initiate a search for service locators belonging to the group ``public'', which is defined by a group value of the empty string "". There is no constant for this, and the locators from Sun do not appear to belong to this group, so most applications will need to follow this up immediately with a call to search for locators belonging to any group:


JoinManager joinMgr = new JoinManager(obj, null, null, null);
joinMgr.setGroups(LookupDiscovery.ALL_GROUPS);

The second constructor


JoinManager(java.lang.Object obj, 
            Entry[] attrSets, 
            java.lang.String[] groups,
            LookupLocator[] locators,
            ServiceIDListener callback,
            LeaseRenewalManager leaseMgr) 
adds groups and locators. This allows multicast search for locators belonging to certain groups, and also unicast lookup for known locators. A multicast only search for any groups would use

JoinManager joinMgr = new JoinManager(obj, null, 
                                      LookupDiscovery.ALL_GROUPS,
                                      null, null, null);
where both additional parameters are set to null. On the other hand, a unicast lookup for a single known site would be done by

LookupLocator[] locators = new LookupLocator[1];
locators[0] new LookupLocator("http://www.all_about_files.com");
JoinManager joinMgr = new JoinManager(obj, null, 
                                      LookupDiscovery.NO_GROUPS,
                                      locators, null, null);
(This code ignored exception handling.)

For example, uploading the complete service of the complete package can become


package joinmgr;

import complete.FileClassifierImpl;

import com.sun.jini.lookup.JoinManager;
import net.jini.core.lookup.ServiceID;
import com.sun.jini.lookup.ServiceIDListener;
import com.sun.jini.lease.LeaseRenewalManager;
import net.jini.discovery.LookupDiscovery;

/**
 * FileClassifierServer1_0.java
 */

public class FileClassifierServer1_0 implements ServiceIDListener {
    
    public static void main(String argv[]) {
	new FileClassifierServer1_0();

        // stay around long enough to receive replies
        try {
            Thread.currentThread().sleep(1000000L);
        } catch(java.lang.InterruptedException e) {
            // do nothing
        }

    }

    public FileClassifierServer1_0() {

	JoinManager joinMgr = null;
	try {
	    /* this is one way of doing it
	    joinMgr = new JoinManager(new FileClassifierImpl(),
				      null,
				      this,
				      new LeaseRenewalManager());
	    joinMgr.setGroups(null);
	    */
	    /* here is another */
	    joinMgr = new JoinManager(new FileClassifierImpl(),
				      null,
				      LookupDiscovery.ALL_GROUPS,
				      null,
				      this,
				      new LeaseRenewalManager());
	} catch(Exception e) {
	    e.printStackTrace();
	    System.exit(1);
	}
    }

    public void serviceIDNotify(ServiceID serviceID) {
	System.out.println("got service ID " + serviceID.toString());
    }
    
} // FileClassifierServer1_0

11.2.1 Getting information from JoinManager

The JoinManager would appear to be unhelpful in supplying information about the lookup locators it finds. It is available, but by a slightly circuitous route. A service can register a ServiceIDListener to the JoinManager. This will be invoked whenever a new locator is found, by its serviceIDNotify() method. A ServiceID is not particularly useful, so we just ignore it. However, within this method we do know that a new service locator has been found.

The complete set of service locators may be found from the JoinManager method getJoinSet(), whuch returns an array of ServiceRegistrar's. We have met this class before: its method getLocator() will return a LookupLocator, which has information such as host in getHost(). These can be put together as


protected JoinManager joinmgr;
...

joinmgr = new JoinManager(service, null, 
                                          this, new LeaseManager());
...

public  void serviceIDNotify(ServiceID serviceID) {
    ServiceRegistrar registrars = joinmgr.getJoinSet();
    for (int n = 0; n < registrar.length; n++) {
        LookupLocator locator = registrars[n].getLocator();
	String hostName = locator.getHost();
	...
    }
}

If you want to find out which is the latest locator to be found, it looks like you will have to cache the previous set, and find which is new in the array returned. Each call to getJoinSet() will return a new array.

11.3. Summary

A JoinManager can be used by a server to simplify many of the aspects of locating lookup services, registering one or more services and renewing leases for them.


If you found this chapter of value, the full book is available from APress or Amazon . There is a review of the book at Java Zone


This file is Copyright (©) 1999, 2000, 2001 by Jan Newmarch (http://jan.netcomp.edu.au) jan.newmarch@jan.newmarch.name.

This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v0.4 or later (the latest version is presently available at http://www.opencontent.org/openpub/). Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.