|
Inexact Service MatchingSuppose you have a printer service that prints at 30 pages per minute. A client wishes to find a printer that will print at least 24 pages per minute. How will this client find the service? The standard Jini pattern matching will either be for an exact match on an attribute or an ignored match on an attribute, so the only way a client can find this printer is to ignore the speed attribute and perform a later selection among all the printers that it sees. We can define a simple printer interface that will allow us to print documents and also allow us to access the printer speed as follows : package common; import java.io.Serializable; /** * Printer.java */ public interface Printer extends Serializable { public void print(String str); public int getSpeed(); } // Printer I don't want to delve here into the complexities of building a real printer service. A "fake" printer implementation that takes its speed from a parameter in the constructor can be written as a complete uploadable service (see Chapter 3) as follows: package printer; /** * PrinterImpl.java */ public class PrinterImpl implements common.Printer, java.io.Serializable { protected int speed; public PrinterImpl(int sp) { speed = sp; } public void print(String str) { // fake stuff: System.out.println("I'm the " + speed + " pages/min printer"); System.out.println(str); } public int getSpeed() { return speed; } } // PrinterImpl Printer implementations can be created and made available using server implementations of earlier chapters. Given this, a client can choose a suitably fast printer in a two-step process:
The following program shows how you can find a printer that is "fast enough": package client; import common.Printer; 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; /** * TestPrinterSpeed.java */ public class TestPrinterSpeed implements DiscoveryListener { public TestPrinterSpeed() { 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[] {Printer.class}; ServiceTemplate template = new ServiceTemplate(null, classes, null); for (int n = 0; n < registrars.length; n++) { ServiceRegistrar registrar = registrars[n]; ServiceMatches matches; try { matches = registrar.lookup(template, 10); } catch(java.rmi.RemoteException e) { e.printStackTrace(); continue; } // NB: matches.totalMatches may be greater than matches.items.length for (int m = 0; m < matches.items.length; m++) { Printer printer = (Printer) matches.items[m].service; // Inexact matching is not performed by lookup() // we have to do it ourselves on each printer // we get int speed = printer.getSpeed(); if (speed >= 24) { // this one is okay, use its print() method printer.print("fast enough printer"); } else { // we can't use this printer, so just say so System.out.println("Printer too slow at " + speed); } } } } public void discarded(DiscoveryEvent evt) { // empty } public static void main(String[] args){ TestPrinterSpeed f = new TestPrinterSpeed(); // stay around long enough to receive replies try { Thread.currentThread().sleep(10000L); } catch(java.lang.InterruptedException e) { // do nothing } } } // TestPrinterSpeed |