Top Banner
Using Lookup Services 1. What are Lookup Services 2. How Clients use lookup services 3. How Services use lookup services 4. Using events
42

Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

Dec 21, 2015

Download

Documents

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

Using Lookup Services

1. What are Lookup Services

2. How Clients use lookup services

3. How Services use lookup services

4. Using events

Page 2: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

Lookup services are Jini services

Every lookup service supports all the abilities & properties of other Jini services:

• Every lookup service has a unique ID

• Every lookup service manages leases

• Every lookup service publishes proxies & attributes

Page 3: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

How Is a Lookup Service Different?

The only difference between a lookup service proxy and other service proxies is that:

• Lookup services proxies can be found by discovery.

• Every lookup service holds a ref to its own proxy + proxies of other lookup services .

Why?

Page 4: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

Why does the LUS hold a proxy to itself?

1. It is possible to add attributes to the proxy so clients can find them by attributes

2. It provides a uniform and elegant way to access resources in the Jini network

3. It gives the ability to create a kind of “nested” LUS by holding the proxies of other LUS in every LUS

Now let’s see how to use the lookup service

Page 5: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

How clients use lookup service?

Clients can use a lookup service in a number of ways:

1. They can ask for the service by ID from the LUS or by attributes.

2. They can ask the LUS to notify them every time a new service appears or any changes are made in the services.

Page 6: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

How services use lookup service?

• First of all : every service has a unique ID . This id is given to it the very first time it runs and stays with it forever!Communicating between LUS and a service is via the join protocol which holds all the info that the service needs for communicating with the LUSAfter the discovery process finds an LUS, the service holds a lease to the LUS that should be renewed as long as the service is active .

Page 7: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

client

• Client life cycle

• The lookup() functions

• How are templates matched ?

• ServiceInfo (code)

Page 8: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

How clients use lookup service

The client life cycle

Clients begin their search for services by using discovery to find LUS, once they found one they interact directly with the ServiceRegistrar interface.

Clients don’t have orders or instructions how to interact with the LUS ( they don’t have the equivalent to the “join protocol”)

Why is that?

Services are longer-lived entities than clients!

Page 9: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

Searching for services

The ServiceRegistrar interface supports two variants of the method called lookup().

1.for clients that can completely specify the service they need by using the template mechanism

2.for client that cant specify the service they need , or for applications that need to find all the available services.

In both versions of the lookup() the client a template called ServiceTemplate

- In the first lookup version the the LUS will return null value to the client if no service matches the template , but if one or more services matches the template the LUS will select one and return its proxy object to the client.

- In the second version the client also passes an integer describing the max number of matches it whishes to have , in this case the LUS returns an array of ServiceItems called ServiceMatches .

Once the client has this array it can just look for service it needs by iterate over the array.

Page 10: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

package net.jini.core.lookup;

public class ServiceMatches

implements Serializable {

public ServiceMatches(ServiceItem[] items , int totalMatches);

public ServiceItem items;

public int totoalMatches ;

}

The ServiceItems returned from the lookup() are copies of the ServiceItems published by the services !!

package net.jini.core.lookup;

public class ServiceItem

implements Serializable {

public ServiceItem(ServiceID serrviceID , Object service , Entry[] attributeSets);

public ServiceID serviceID;

public Object service ;

public Entry[] attributeSets;

}

Page 11: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

How are templates matched??

package net.jini.core.lookup;

public class ServiceTemplate

implements Serializable {

public ServiceTemplate(ServiceID serviceID , Class[] serviceTypes , Entry[] attrSetTmpls);

public ServiceID serviceID;

public Class[] serviceTypes ;

public Entry[] attrSetTempls;

}

Page 12: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

Matches if:

*the service ID in the template matches the ID of the registered service or if the ID field is null.

And

*the registered service is an instance of every type in the serviceTypes or if this field is null.

And

*the service’s list of att contains at least one attribute that matches every entry in the template , or if this field is null.

Page 13: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

// Find and print services that have ServiceInfo

// attributes.

 import net.jini.discovery.LookupDiscovery;

import net.jini.discovery.DiscoveryEvent;

import net.jini.discovery.DiscoveryListener;

import net.jini.core.lookup.ServiceMatches;

import net.jini.core.lookup.ServiceItem;

import net.jini.core.lookup.ServiceTemplate;

import net.jini.core.lookup.ServiceRegistrar;

import net.jini.lookup.entry.ServiceInfo;

import net.jini.core.entry.Entry;

import java.util.Hashtable;

import java.rmi.RemoteException;

import java.rmi.RMISecurityManager;

import java.io.IOException;

 

public class ServiceInfoSearcher implements Runnable {

protected Hashtable registrars = new Hashtable();

protected Hashtable services = new Hashtable();

protected ServiceTemplate tmpl;

Page 14: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

class Discoverer implements DiscoveryListener {

public void discovered(DiscoveryEvent ev) {

ServiceRegistrar[] newregs = ev.getRegistrars();

for (int i=0 ; i<newregs.length ; i++) {

addRegistrar(newregs[i]);

}

}

public void discarded(DiscoveryEvent ev) {

ServiceRegistrar[] newregs = ev.getRegistrars();

for (int i=0 ; i<newregs.length ; i++) {

removeRegistrar(newregs[i]);

}

}

}

public ServiceInfoSearcher() throws IOException {

if (System.getSecurityManager() == null) {

System.setSecurityManager(

new RMISecurityManager());

}

Page 15: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

// build our template

Entry[] attrTemplates = new Entry[1];

attrTemplates[0] = new ServiceInfo(null, null, null,

null, null, null);

tmpl = new ServiceTemplate(null, null, attrTemplates);

// set up for discovery

LookupDiscovery disco =

new LookupDiscovery(LookupDiscovery.ALL_GROUPS);

disco.addDiscoveryListener(new Discoverer());

}

protected synchronized void addRegistrar(ServiceRegistrar reg) {

if (registrars.contains(reg.getServiceID()))

return;

registrars.put(reg.getServiceID(), reg);

findServices(reg);

}

protected synchronized void removeRegistrar(ServiceRegistrar reg) {

if (!registrars.contains(reg.getServiceID()))

return;

Page 16: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

registrars.remove(reg.getServiceID());

}

void findServices(ServiceRegistrar reg) {

try {

ServiceMatches matches = reg.lookup(tmpl, Integer.MAX_VALUE);

for (int i=0 ; i<matches.totalMatches ; i++) {

if (services.contains(matches.items[i].serviceID))

continue;

addService(matches.items[i]);

}

} catch (RemoteException ex) {

System.err.println("Couldn't search for services: " +

ex.getMessage());

}

}

}

Page 17: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

protected void addService(ServiceItem item) {

services.put(item.serviceID, item);

System.out.println("New service found: " + item.serviceID);

printServiceInfo(item);

}

protected void printServiceInfo(ServiceItem item) {

for (int i=0 ; i<item.attributeSets.length ; i++) {

if (item.attributeSets[i] instanceof ServiceInfo) {

ServiceInfo info = (ServiceInfo) item.attributeSets[i];

System.out.println(" Name = " + info.name);

System.out.println(" Manufacturer = " + info.manufacturer);

System.out.println(" Vendor = " + info.vendor);

System.out.println(" Version = " + info.version);

System.out.println(" Model = " + info.model);

System.out.println(" Serial Number = " + info.serialNumber);

}

}

}

Page 18: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

public void run() {

while (true) {

try {

Thread.sleep(Long.MAX_VALUE);

} catch (InterruptedException ex) {

}

}

}

public static void main(String args[]) {

try {

ServiceInfoSearcher searcher = new ServiceInfoSearcher();

new Thread(searcher).start();

} catch (Exception ex) {

System.err.println("Error starting service info searcher: " +

ex.getMessage());

ex.printStackTrace();

}

}

}

Page 19: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

service

• The Join protocol

• Basic wrapper uses JoinManager (code)

Page 20: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

The join protocol

In order to “find “ a LUS, the service needs to perform the following steps:

A. Create a ServiceItem that holds both the proxy & the attributes of the service

B. Publish the service by calling register() on any ServiceRegistrars found in the discovery process

C. Maintain the lease returned from the LUS

Page 21: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

A good Jini citizen, joins…

In addition there are some more things that the service should do in order to be considered as a nice Jini network member:

• The Service should use the same unique ID even across restart and fails.

• The Service should hold a list of LUS it expects to join, this list must survive across restart and fails

• When a service starts it should register itself with all the LUS in the list using unicast discovery.

Page 22: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

Handling Leases, Attribute and group updates

• Services renew their leases on registrations, if at any point the communication with the LUS fails, the service acts depending on how the LUS was discovered:

• If the LUS discovered via multicast discovery the service should simply forget it by calling discard() .

• If the LUS was discovered by the unicast discovery, meaning that the LUS was on the service list, the service should try to reconnect .

• If the service changes the set of attributes, or is asked to do so, then it should make the change in all the LUS it registered with.

• If the service changes the set of groups it is member of, or is asked to do so, then it has to drop itself from all the LUS that are not in the new group, and start the discovery process on the LUS that are members in the new group.

Page 23: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

// A basic wrapper that uses JoinManager

 

package corejini.chapter8;

 

import java.io.*;

import net.jini.core.lookup.ServiceID;

import net.jini.core.discovery.LookupLocator;

import net.jini.core.entry.Entry;

import com.sun.jini.lookup.JoinManager;

import com.sun.jini.lookup.ServiceIDListener;

import java.rmi.RMISecurityManager;

 

class MyProxy implements Serializable,

corejini.chapter5.HelloWorldServiceInterface {

public MyProxy() { }

public String getMessage() {

return "Bonjour, my little turnip...";

}

}

Page 24: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

public class ServiceWrapper implements Runnable {

protected JoinManager join = null;

protected File serFile = null;

protected Object proxy = new MyProxy();

// note static!

static class PersistentData implements Serializable {

ServiceID serviceID;

Entry[] attrs;

String[] groups;

LookupLocator[] locators;

public PersistentData() {

}

}

Page 25: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

// An inner class to catch ID changes

class IDListener implements ServiceIDListener {

public void serviceIDNotify(ServiceID serviceID) {

System.out.println("Got service ID " + serviceID);

PersistentData state = new PersistentData();

state.serviceID = serviceID;

state.attrs = join.getAttributes();

state.groups = join.getGroups();

state.locators = join.getLocators();

try {

writeState(state);

} catch (IOException ex) {

System.err.println("Couldn't write to file: " +

ex.getMessage());

ex.printStackTrace();

join.terminate();

System.exit(1);

}}}

Page 26: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

public ServiceWrapper(File serFile, boolean firsttime)

throws IOException, ClassNotFoundException {

this.serFile = serFile;

  if (System.getSecurityManager() == null) {

System.setSecurityManager( new RMISecurityManager());

}

if (firsttime)

register();

else

reregister();

}

public void run() {

while (true) {

try {

Thread.sleep(Long.MAX_VALUE);

} catch (InterruptedException ex) {

}

Page 27: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

protected void register() throws IOException {

if (join != null) {

throw new IllegalStateException("Wrapper already started.");

}

System.out.println("Starting...");

join = new JoinManager(proxy, null, new IDListener() , null);

}

protected void reregister() throws IOException, ClassNotFoundException {

if (join != null) {

throw new IllegalStateException("Wrapper already started.");

}

Page 28: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

PersistentData state = readState();

System.out.println("Restarting: old id is " +

state.serviceID);

join = new JoinManager(state.serviceID, proxy, state.attrs, state.groups,

state.locators, null);

}

 

protected void writeState(PersistentData state) throws IOException {

ObjectOutputStream out =

new ObjectOutputStream(new FileOutputStream(serFile));

out.writeObject(state);

out.flush();

out.close();

}

Page 29: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

protected PersistentData readState()

throws IOException, ClassNotFoundException {

ObjectInputStream in = new ObjectInputStream(New FileInputStream(serFile)); PersistentData state = (PersistentData)

in.readObject();

in.close();

return state;

}

static void usage() {

System.err.println("Usage: ServiceWrapper " +

"[-f] serialization_file");

System.exit(1);

}

Page 30: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

public static void main(String[] args) {

boolean firsttime = false;

String serFileName = null;

File serFile = null;

if (args.length < 1 || args.length > 2) {

usage();

}

if (args.length == 2) {

if (args[0].equals("-f")) {

firsttime = true;

serFileName = args[1];

} else {

usage();

}

} else {

serFileName = args[0];

}

serFile = new File(serFileName);

}

Page 31: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

try {

ServiceWrapper wrapper =

new ServiceWrapper(serFile, firsttime);

new Thread(wrapper).start();

} catch (Exception ex) {

ex.printStackTrace();

}

}

}

Page 32: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

events

• Soliciting events from LUS

• Receiving events

• Using events (code)

Page 33: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

Soliciting events from lookup service

1. Why would a client be interesting in events?

2. How client ask to be notified on event?

3. What kinds of events can happened ?

4. How lookup service notifies the client ?

Page 34: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

•When a client ask for events to be sent to him he provides a special flag that determines how the template is used

•The flag can have three possible values:

1.a service suddenly matches the provided template.

2.a service is no longer matches.

3.a service is still matching but is changing.

•Client is asking for events by calling notify() method on the ServiceRegistrar

The flags are:

int TRANSITION_MATCH_NOMATCH = 1 << 1; // template doesn’t match a given service

int TRANSITION_NOMATCH_MATCH = 1 << 1; // template begins to match the service

int TRANSITION_MATCH_MATCH = 1 << 2; // a service is changing in some way

The notify() method returns an EventRegistration to the client .(a simple container class that contains the source of the event in this case the ServiceRegistrar that generate the event) , and lease for the event registration .

How the client receive the event ?

Page 35: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

Receiving events !

Requesting for event the client provides an object that implements the RemoteEventLisener interface

public interface RemoteEventLisener implements java.rmi.Remote, java.util.EventLisener {

public void notify(RemoteEvent ev)

throws java.rmi.RemoteExeption , UnknownEventExeption;

}

Whenever a LUS needs to send an event , it will construct one and deliver it by calling the notify().

The LUS delivers a subclass of RemoteEvent that provides extra info about the change .

Page 36: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

This subclass is called ServiceEvent.

In the ServiceEvent client can find info about the service by using the methods

getServiceID(). -- that returns the service id.

getServiceItem(). -- returns the complete service item that cause the event.

a new item if the service has changed.

returns null if the service was deleted.

getTransition(). -- returns a flag value indicating what type of transition occurred

Page 37: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

// like lookup searcher, only uses events

 

package corejini.chapter8;

 

import net.jini.core.lookup.ServiceRegistrar;

import net.jini.core.lookup.ServiceEvent;

import net.jini.core.lookup.ServiceItem;

import net.jini.core.event.RemoteEvent;

import net.jini.core.event.EventRegistration;

import net.jini.core.event.RemoteEventListener;

import net.jini.core.lease.Lease;

import com.sun.jini.lease.LeaseRenewalManager;

import java.rmi.RemoteException;

import java.rmi.server.UnicastRemoteObject;

import java.util.Hashtable;

import java.io.IOException;

Page 38: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

public class ServiceInfoWatcher extends ServiceInfoSearcher {

protected Listener listener;

protected LeaseRenewalManager mgr;

protected Hashtable leases = new Hashtable();

protected int transitions =

ServiceRegistrar.TRANSITION_MATCH_NOMATCH |

ServiceRegistrar.TRANSITION_NOMATCH_MATCH |

ServiceRegistrar.TRANSITION_MATCH_MATCH;

class Listener extends UnicastRemoteObject

implements RemoteEventListener {

public Listener() throws RemoteException {

}

public void notify(RemoteEvent ev) throws RemoteException {

if (!(ev instanceof ServiceEvent)) {

System.err.println("Unexpected event: " +

ev.getClass().getName());

return;

}

Page 39: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

ServiceEvent serviceEvent = (ServiceEvent) ev;

switch (serviceEvent.getTransition()) {

case ServiceRegistrar.TRANSITION_NOMATCH_MATCH:

addService(serviceEvent.getServiceItem());

break;

case ServiceRegistrar.TRANSITION_MATCH_NOMATCH:

removeService(serviceEvent.getServiceItem());

break;

case ServiceRegistrar.TRANSITION_MATCH_MATCH:

serviceChanged(serviceEvent.getServiceItem());

break;

}

}

}

public ServiceInfoWatcher()

throws IOException, RemoteException {

mgr = new LeaseRenewalManager();

listener = new Listener();

}

Page 40: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

protected void removeService(ServiceItem item) {

services.remove(item.serviceID);

System.out.println("Service no longer available: " + item.serviceID);

printServiceInfo(item);

}

protected void serviceChanged(ServiceItem item) {

services.put(item.serviceID, item);

System.out.println("Service updated: " + item.serviceID);

printServiceInfo(item);

}

// overrride addRegistrar and removeRegistrar to have them

// ask for/terminate event solicitations whenever we find a

// lookup service.

protected void addRegistrar(ServiceRegistrar reg) {

try {

super.addRegistrar(reg);

EventRegistration er = reg.notify(tmpl , transitions,listener,

null,10 * 60 * 1000);

Page 41: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

// do something with lease

leases.put(reg.getServiceID(), er.getLease());

mgr.renewFor(er.getLease(), Long.MAX_VALUE, null);

} catch (RemoteException ex) {

System.err.println("Can't solicit event: " +

ex.getMessage());

}

}

protected void removeRegistrar(ServiceRegistrar reg) {

try {

super.removeRegistrar(reg);

// terminate leases on this dude.

Lease lease = (Lease) leases.get(reg.getServiceID());

if (lease == null)

return;

leases.remove(reg.getServiceID());

Page 42: Using Lookup Services 1.What are Lookup Services 2.How Clients use lookup services 3.How Services use lookup services 4.Using events.

// May raise unknown lease exception or

// remote exception. Should be ok to ignore

// here...

mgr.cancel(lease);

} catch (Exception ex) {

}

}

public static void main(String[] args) {

try {

ServiceInfoWatcher watcher = new ServiceInfoWatcher();

new Thread(watcher).start();

} catch (Exception ex) {

System.err.println("Error starting watcher: " +

ex.getMessage());

}

}

}