previous chapter table of contents next chapter

Monitoring Changes in Services

Services will start and stop. When they start, they will inform the lookup services, and sometime after they stop, they will be removed from the lookup services. However, there are a lot of times when other services or clients will want to know when services start or are removed. For example, an editor may want to know if a disk service has started so that it can save its file; a graphics display program may want to know when printer services start up; the user interface for a camera may want to track changes in disk and printer services so that it can update the Save and Print buttons .

A service registrar acts as a generator of ServiceEvent type events, which sub-class from RemoteEvent . These events are generated in response to changes in the state of services that match (or fail to match) a template pattern for services. This event type has three categories from the ServiceEvent.getTransition() method:

  • TRANSITION_NOMATCH_MATCH : A service has changed state so that whereas it previously did not match the template, now it does. In particular, if it didn't exist before, now it does. This transition type can be used to spot new services starting or to spot wanted changes in the attributes of an existing registered service; for example, an offline printer can change attributes to being online, which now makes it a useful service.
  • TRANSITION_MATCH_NOMATCH: A service has changed state so that whereas it previously did match the template, now it doesn't. This can be used to detect when services are removed from a lookup service. This transition can also be used to spot changes in the attributes of an existing registered service that are not wanted; for example, an online printer can change attributes to being offline.
  • TRANSITION_MATCH_MATCH : A service has changed state, but it matched both before and after. This typically happens when an Entry value changes, and it is used to monitor changes of state, such as a printer running out of paper, or a piece of hardware signaling that it is due for maintenance work.

A client that wants to monitor changes of services on a lookup service must first create a template for the types of services it is interested in. A client that wants to monitor all changes could prepare a template such as this:

 ServiceTemplate templ = new ServiceTemplate(null, null, null); // or ServiceTemplate templ = new ServiceTemplate(null, new Class[] {}, new Entry[] {}); // or ServiceTemplate templ = new ServiceTemplate(null, new Class[] {Object.class}, null); 

It then sets up a transition mask as a bit-wise OR of the three service transitions, and then calls notify() on the ServiceRegistrar object. The following is a program to monitor all changes.

 /**  * RegistrarObserver.java  */ package observer; import net.jini.core.event.RemoteEventListener; import net.jini.core.event.RemoteEvent; import net.jini.core.lookup.ServiceEvent; import net.jini.core.lookup.ServiceRegistrar; import net.jini.core.lease.Lease; import net.jini.core.lookup.ServiceTemplate; import net.jini.core.lookup.ServiceID; import net.jini.core.event.EventRegistration; // import com.sun.jini.lease.LeaseRenewalManager; // Jini 1.0 import net.jini.lease.LeaseRenewalManager;        // Jini 1.1 import net.jini.core.lookup.ServiceMatches; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import net.jini.core.entry.Entry; import net.jini.core.event.UnknownEventException; public class RegistrarObserver extends UnicastRemoteObject implements                                RemoteEventListener {       protected static LeaseRenewalManager leaseManager = new LeaseRenewalManager();     protected ServiceRegistrar registrar;     protected final int transitions = ServiceRegistrar.TRANSITION_MATCH_NOMATCH                                    ServiceRegistrar.TRANSITION_NOMATCH_MATCH                                    ServiceRegistrar.TRANSITION_MATCH_MATCH; public RegistrarObserver() throws RemoteException { } public RegistrarObserver(ServiceRegistrar registrar) throws RemoteException {     this.registrar = registrar;     ServiceTemplate templ = new ServiceTemplate(null, null, null);     EventRegistration reg = null;     try {         // eventCatcher = new MyEventListener();         reg = registrar.notify(templ,                          transitions,                          this,                           null,                          Lease.ANY);         System.out.println("notified id " + reg.getID());   } catch(RemoteException e) {       e.printStackTrace();   }   leaseManager.renewUntil(reg.getLease(), Lease.FOREVER, null); } public void notify(RemoteEvent evt)     throws RemoteException, UnknownEventException {     try {         ServiceEvent sevt = (ServiceEvent) evt;         int transition = sevt.getTransition();         System.out.println("transition " + transition);         switch (transition) {         case ServiceRegistrar.TRANSITION_NOMATCH_MATCH:             System.out.println("nomatch -> match");             break;         case ServiceRegistrar.TRANSITION_MATCH_MATCH:             System.out.println("match -> match");             break;         case ServiceRegistrar.TRANSITION_MATCH_NOMATCH:             System.out.println("match -> nomatch");             break;         }         System.out.println(sevt.toString());         if (sevt.getServiceItem() == null) {             System.out.println("now null");         } else {             Object service = sevt.getServiceItem().service;             System.out.println("Service is " + service.toString());         }      } catch(Exception e) {         e.printStackTrace();     }    } // RegistrarObserver 

The following is a suitable driver for the preceding observer class:

 package client; import java.rmi.RMISecurityManager; import java.rmi.RemoteException; 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 java.util.Vector; import observer.RegistrarObserver; /**  * ReggieMonitor.java   */ public class ReggieMonitor implements DiscoveryListener {     protected Vector observers = new Vector();     public static void main(String argv[]) {         new ReggieMonitor();         // stay around long enough to receive replies         try {             Thread.currentThread().sleep(100000L);         } catch(java.lang.InterruptedException e) {             // do nothing         }     }     public ReggieMonitor() {         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();         for (int n = 0; n < registrars.length; n++) {             System.out.println("Service lookup found");             ServiceRegistrar registrar = registrars[n];             if (registrar == null) {                 System.out.println("registrar null");                 continue;             }             try {                 System.out.println("Lookup service at " +                                registrar.getLocator().getHost());             } catch(RemoteException e) {                 System.out.println("Lookup service info unavailable");             }             try {                 observers.add(new RegistrarObserver(registrar));             } catch(RemoteException e) {                 System.out.println("adding observer failed");             }             ServiceTemplate templ = new ServiceTemplate(null, new Class[] {Object.class}, null);             ServiceMatches matches = null;             try {                 matches = registrar.lookup(templ, 10);             } catch(RemoteException e) {                 System.out.println("lookup failed");             }             for (int m = 0; m < matches.items.length; m++) {                 if (matches.items[m] != null && matches.items[m].service != null) {                     System.out.println("Reg knows about " + matches.items[m].service.toString() +                                    " with id " + matches.items[m].servieID);                 }              }         }     }     public void discarded(DiscoveryEvent evt) {         // remove observer     } } // ReggieMonitor 

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