Client Search

A client searches for a service from a lookup service using the ServiceRegistrar object supplied from the lookup service:


public Class ServiceRegistrar {
    public java.lang.Object lookup(ServiceTemplate tmpl)
                            throws java.rmi.RemoteException;
    public ServiceMatches lookup(ServiceTemplate tmpl,
                                 int maxMatches)
                            throws java.rmi.RemoteException;
}
The first of these methods just finds a service that matches the request. The second finds a set (upto the maxMatches) requested.

The lookup methods use a class of type ServiceTemplate to specify the service looked for:


package net.jini.core.lookup;

public Class ServiceTemplate {
    public ServiceID serviceID;
    public java.lang.Class[] serviceTypes;
    public Entry[] attributeSetTemplates;

    ServiceTemplate(ServiceID serviceID, 
                    java.lang.Class[] serviceTypes, 
                    Entry[] attrSetTemplates);
}
The serviceID is null if unknown (when could the client be expected to know it??? If it is repeating a request???). TheattributeSetTemplates is a set of Entry elements to perform matching of attributes, as discussed earlier (will be done???).

The major parameter to the lookup() method is a list of serviceTypes. Each service exported is an instance of a class; however, an instance of the class cannot be used in a search, because then the client would already have it and would not need to search! The next best thing is a Class object, because then the exported service can be checked to be an instance of that class. But if you have a class object, then why not simply new it on the client side? In general, exported class would be subclasses of the class requested, and in these subclasses would offer more than the client can get just by new'ing the class. So the client will request a superclass object, or an interface object.

To be more concrete, a toaster may be defined by an interface


public interface Toaster {
    void setDarkness(int dark);
    void startToasting();
}
A Breville ``Extra Lift'' toaster will implement this in one particular way, as will other toasters

public Class BrevilleExtraLiftToaster implements Toaster {
    void setDarkness(int dark) {
        ...
    }
    void startToasting() {
        ...
    }
}
When the toaster service starts, it exports an object of class BrevilleExtraLiftToaster to the lookup service. However, the client does not know what type of toaster is out there, so will make a request such as

    Class[] toasterClasses = new Class[1];
    Toaster toaster = null;
    try {
        toasterClasses[0] = new Class.forName("Toaster");
    } catch(ClassNotFoundException e) {
        System.err.exit(1);
    }
    ServiceTemplate template = new ServiceTemplate(null, classes, 
                                                   null);
    try {
        toaster = (Toaster) registrar.lookup(template);
    } catch(java.rmi.RemoteException e) {
        System.err.exit(2);
    }
Notice that the lookup can throw an exception. This can occur, if say, the service requested is not serialisable.

At the end of this, an object has been transported across to the client that is an instance of a class implementing the Toaster interface, and has been coerced to be of this type. This object has two methods setDarkness() and startToasting(). No other information is available about the toaster capabilities, because the interface does not specify any more and in this case the set of attribute values was null. So the client can call


    toaster.setDarkness(1);
    toaster.startToasting();

1. ServiceMatches

If a client wishes to search for more than one match to a service request from a particular lookup service, then it specify the maximum number of matches it would like returned as a ServiceMatches object.


package net.jini.core.lookup;

public Class ServiceMatches {
    public ServiceItem[] items;
    public int totalMatches ;
}
The number of elements in items will be the same as totalMatches. However, not all elements of this array need be non-null! Note that in the above when asking for only one match, and exception can be returned, say when the service is not serialisable. No exception is thrown here, because although one element might be bad, the others may still be okay. So a value of null is used to signify this

    ServiceMatches matches = registrar.lookup(template, 10);
    for (int n = 0; n < matches.totalMatches; n++) {
        Toaster toaster = (Toaster) matches.items[n];
	if (toaster != null) {
	    toaster.setDarkness(1);
	    toaster.startToasting();
        }
    }
(which will start upto 10 toasters cooking at once!)

This file is Copyright ©Jan Newmarch (http://jan.newmarch.name) jan@newmarch.name

The copyright is the OpenContent License (http://www.opencontent.org/opl.shtml), which is the ``document'' version of the GNU OpenSource license.