previous chapter table of contents next chapter

Finding a Service Once Only

There may be many lookup services on the local network, perhaps specializing in certain groups of services. There could be many lookup services running on the Internet, which could act as global repositories of information. For example, there is a lookup service running at http://www.jini.canberra.edu.au that acts as a publicly available lookup service for those who wish to experiment with Jini. One may expect to find lookup services acting in a "portal" role, listing all of the public clock services, the real estate services, and so on.

A service will probably register with as many service locators as it can to improve its chances of being found. On the other hand, clients looking for a ser- vice may be content to find just a single suitable implementation, or may wish to find all service implementations . This second case can cause some uniqueness problems: if a client finds every service that has been registered with multiple locators, then it will probably find the same service more than once.

Why is this a problem? Well, suppose the client wants to find all power drills in the factory and ask them to drill exactly one hole each. Or suppose it finds all backup services for the system, and wants each one to perform a single backup. In that case, it needs to know the identity of each service so that it can tell when it is getting a duplicate copy from another locator source. Otherwise, each drill might make six holes because the client got a copy of each drill from six service locators, or you might get six backups of the same data. Whenever a service can perform a non-idempotent service (i.e., one in which repeating the action has a different effect each time), then duplicate copies on the client side must be avoided.

Jini has a concept of a service being a "good citizen." This concept includes having a single identity across all lookup services, which allows clients to tell whether they have come across multiple copies of the same service or have encountered a different implementation of the service. The behavior on the part of services is contained in the Jini "Lookup Service" specification, and it hinges on the use of the ServiceID .

A ServiceID can be specified when registering a service with a service locator. If this is the first time this service has ever been registered, then the ServiceID should be null. The service locator will then generate a non-null ServiceID that can be used in future to identify this service. This object is specified to be unique, so that a service locator cannot generate the same ServiceID for two different services, and two different locators cannot generate the same ServiceID . This provides a unique identifier that can be used to identify duplicates.

The procedure for a service to follow when it is registering itself with service locators is as follows :

  1. The very first time a service is registered, use null as the serviceID value of the ServiceItem in ServiceRegistrar.register() .
  2. The returned ServiceRegistration has a getServiceID() method for retrieving the ServiceID . This ServiceID should then be used in any future registrations both with this service locator and with any others. This ensures that the service has a unique identity across all lookup services. It should be noted that JoinManager already does this, although this is not stated in its documentation. We have done this in earlier examples, such as the server in Chapter 8.
  3. The client has a choice of two lookup() methods to use with its ServiceRegistrar object: the first just returns a single object, and the sec-ond returns an array of ServiceMatches objects. This second one is more useful here, as it can give the array of ServiceItem objects, and the ServiceID can be extracted from there.
  4. The client should maintain a list of service IDs that it has seen, and compare any new ones against it ”then it can check whether a service is a new one or a previously seen one.
  5. The service should save its ID in persistent storage so that if it dies and restarts, it can use the same ID ”after all, it is the same service. (This may involve subtle considerations: it should only use the same ServiceID if it really is the same service. For example, if the service maintains state that is lost in a crash, then it isn't the same service!)

In Chapter 8 we gave the code for a multicast client that looked for a service, used it, and exited. A modified client that looks for all unique services and uses each one is as follows:

 package unique; import common.FileClassifier; import common.MIMEType; import java.rmi.RMISecurityManager; import net.jini.discovery.LookupDiscovery; import net.jini.discovery.DiscoveryListener; import net.jini.discovery.DiscoveryEvent; import net.jini.core.lookup.ServiceRegistrar; import net.jini.core.lookup.ServiceTemplate; import net.jini.core.lookup.ServiceMatches; import net.jini.core.lookup.ServiceItem; import net.jini.core.lookup.ServiceID; import java.util.Vector; /**  * TestFileClassifier.java  */ public class TestFileClassifier implements DiscoveryListener {       protected Vector serviceIDs = new Vector();     public static void main(String argv[]) {         new TestFileClassifier();         // stay around long enough to receive replies         try {             Thread.currentThread().sleep(10000L);         } catch(java.lang.InterruptedException e) {             // do nothing         }     }     public TestFileClassifier() {         System.setSecurityManager(new RMISecurityManager());         LookupDiscovery discover = null;         try {             discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);         } catch(Exception e) {             System.err.println(e.toString());             System.exit(1);         }         discover.addDiscoveryListener(this);     }     public void discovered(DiscoveryEvent evt) {         ServiceRegistrar[] registrars = evt.getRegistrars();         Class [] classes = new Class[] {FileClassifier.class};         FileClassifier classifier = null;         ServiceTemplate template = new ServiceTemplate(null, classes,                                                        null);         for (int n = 0; n < registrars.length; n++) {             System.out.println("Service found");             ServiceRegistrar registrar = registrars[n];             ServiceMatches matches = null;             try {                  matches = registrar.lookup(template, 10);             } catch(java.rmi.RemoteException e) {                 e.printStackTrace();                 continue;             }             ServiceItem[] items = matches.items;             for (int m= 0; m  items.length; m++) {                 ServiceID id= items[m].serviceID;                 if (serviceIDs.indexof(id) != 1 {                     // found a new serviceID - record it and use it                     classifier = (FileClassifier) items[m].service;                     if (Classifier == null) {                             System.out.print("Classifier null");                             continue;                     }                     serviceIDs.add(id);                     MIMEType type;                     try {                         type = clasifier.gerMIMEType("file1.txt");                         System.out.println("Type is " + type.toString());                     } catch(java.rmi.RemoteException e) {                         System.err.println(e.toString());                     }                 }             }         }     }     public void discarded(DiscoveryEvent evt) {         // empty     } } // TestFileClassifier 

A Programmer[ap]s Guide to Jini Technology
A Programmer[ap]s Guide to Jini Technology
ISBN: 1893115801
Year: 2000
Pages: 189

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net