Jan Newmarch
jan@ise.canberra.edu.au
University of Canberra
DSTC (Distributed Systems Technology CRC)
DISCOVERING A LOOKUP SERVICE
Lookup Service
-
Before a client or service can do anything, they find a lookup service
-
Unicast lookup can be made to known locations
-
Multicast search can be made for unknown locations
-
Sun supply a lookup service called
reggie
Unicast discovery
Unicast discovery program
import net.jini.core.discovery.LookupLocator;
import net.jini.core.lookup.ServiceRegistrar;
public class UnicastRegister {
static public void main(String argv[]) {
new UnicastRegister();
}
public UnicastRegister() {
LookupLocator lookup = null;
ServiceRegistrar registrar = null;
try {
lookup = new LookupLocator("jini://localhost");
} catch(java.net.MalformedURLException e) {
System.err.println("Lookup failed: " + e.toString());
System.exit(1);
}
try {
registrar = lookup.getRegistrar();
} catch (java.io.IOException e) {
System.err.println("Registrar search failed: " + e.toString());
System.exit(1);
} catch (java.lang.ClassNotFoundException e) {
System.err.println("Registrar search failed: " + e.toString());
System.exit(1);
}
System.out.println("Registrar found");
// the code takes separate routes from here for client or service
}
} // UnicastRegister
Multicast discovery
-
Broadcast discovery is done using the class
LookupDiscovery
public class LookupDiscovery {
public LookupDiscovery(String[] groups);
addDiscoveryListener(LookupDiscoveryListener l);
}
-
Replies are handled asynchronously by a listener
interface LookupDiscoveryListener {
public void discovered(DiscoveryEvent e);
public void discarded(DiscoveryEvent e);
}
-
The event contains registrar information
public class DiscoveryEvent {
Registrar[] getRegistrars();
}
Multicast discovery program
import net.jini.discovery.LookupDiscovery;
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.DiscoveryEvent;
import net.jini.core.lookup.ServiceRegistrar;
public class MulticastRegister implements DiscoveryListener {
static public void main(String argv[]) {
new MulticastRegister();
// stay around long enough to receive replies
try {
Thread.currentThread().sleep(10000L);
} catch(java.lang.InterruptedException e) {
// do nothing
}
}
public MulticastRegister() {
LookupDiscovery discover = null;
try {
discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);
} catch(Exception e) {
System.err.println(e.toString());
e.printStackTrace();
System.exit(1);
}
discover.addDiscoveryListener(this);
}
public void discovered(DiscoveryEvent evt) {
ServiceRegistrar[] registrars = evt.getRegistrars();
for (int n = 0; n < registrars.length; n++) {
ServiceRegistrar registrar = registrars[n];
// the code takes separate routes from here for client or service
System.out.println("found a service locator");
}
}
public void discarded(DiscoveryEvent evt) {
}
} // MulticastRegister
ServiceRegistrar
-
Both lookup methods return a
ServiceRegistrar
.
This is a proxy for the lookup service
public interface ServiceRegistrar {
public ServiceRegistration register(ServiceItem i,
long leaseDuration);
public Object lookup(ServiceTemplate tmpl);
public ServiceMatches lookup(ServiceTemplate tmpl, int maxMatches);
LookupLocator getLocator();
}
-
The
register()
method is used by a service
-
The
lookup()
methods are used by a client.
The first returns a single service, the second a set of services
-
The
getLocator()
method can say where the lookup service is
ENTRIES
Entry class
Creating entries
Interfaces, implementations and entries
-
A client looks for an instance of an interface
-
It may qualify the search with entries
-
A service exports an implementation of this interface
-
A service will also export additional entry information, as much
as it can
CLIENT
Problem domain
-
Files have a type, that can be described by a MIME type
public class MIMEType implements java.io.Serializable {
protected String contentType;
protected String subType;
public MIMEType(String contentTpe, String subType) {...}
public String toString() {...}
}
(It may need to be serialized, to move it from one machine to another)
-
A file classifier can take a filename and use this to work out the
MIME type, using an internal table
public interface FileClassifier {
MIMEType getMIMEType(String fileName)
throws java.rmi.RemoteException;
}
(The method may be executing remotely, so can throw a remote exception)
Unicast client
Use this pattern when you do know where the lookup locator is:
package client;
import common.FileClassifier;
import common.MIMEType;
import net.jini.core.discovery.LookupLocator;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceItem;
import net.jini.core.lookup.ServiceRegistration;
import java.rmi.RMISecurityManager;
import net.jini.core.lookup.ServiceTemplate;
public class TestUnicastFileClassifier {
public static void main(String argv[]) {
new TestUnicastFileClassifier();
}
public TestUnicastFileClassifier() {
LookupLocator lookup = null;
ServiceRegistrar registrar = null;
FileClassifier classifier = null;
try {
lookup = new LookupLocator("jini://www.all_about_files.com");
} catch(java.net.MalformedURLException e) {
System.err.println("Lookup failed: " + e.toString());
System.exit(1);
}
System.setSecurityManager(new RMISecurityManager());
try {
registrar = lookup.getRegistrar();
} catch (java.io.IOException e) {
System.err.println("Registrar search failed: " + e.toString());
System.exit(1);
} catch (java.lang.ClassNotFoundException e) {
System.err.println("Registrar search failed: " + e.toString());
System.exit(1);
}
Class[] classes = new Class[] {FileClassifier.class};
ServiceTemplate template = new ServiceTemplate(null, classes, null);
try {
classifier = (FileClassifier) registrar.lookup(template);
} catch(java.rmi.RemoteException e) {
e.printStackTrace();
System.exit(1);
}
if (classifier == null) {
System.out.println("Classifier null");
System.exit(2);
}
MIMEType type;
try {
type = classifier.getMIMEType("file1.txt");
System.out.println("Type is " + type.toString());
} catch(java.rmi.RemoteException e) {
System.err.println(e.toString());
}
// System.exit(0);
}
} // TestUnicastFileClassifier
Client and service locator JVM's
The two JVM's look like
Multicast client
Use this pattern when you don't know where the lookup locator(s) are:
package client;
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;
public class TestFileClassifier implements DiscoveryListener {
public static void main(String argv[]) {
new TestFileClassifier();
// stay around long enough to receive replies
try {
Thread.currentThread().sleep(100000L);
} 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];
try {
classifier = (FileClassifier) registrar.lookup(template);
} catch(java.rmi.RemoteException e) {
e.printStackTrace();
System.exit(2);
}
if (classifier == null) {
System.out.println("Classifier null");
continue;
}
MIMEType type;
try {
type = classifier.getMIMEType("file1.txt");
System.out.println("Type is " + type.toString());
} catch(java.rmi.RemoteException e) {
System.err.println(e.toString());
}
// System.exit(0);
}
}
public void discarded(DiscoveryEvent evt) {
// empty
}
} // TestFileClassifier
PROXY IMPLEMENTATION CHOICES
Proxy is the Service
-
The complete service may be uploaded, so there is no separate proxy
-
The client uses
FileClassifier
-
The server creates a
FileClassifierImpl
-
The server exports the
FileClassifierImpl
-
This is a ``fat'' proxy model, with no processing being done on the
server side
-
This is suitable for software services that do not need to maintain state
on the server side
RMI Proxies
-
If RMI stubs are used to implement the proxy, it looks like
-
The client uses
FileClassifier
-
The server creates a
FileClassifierImpl
-
The RMI runtime ensures that a
FileClassifierimpl_Stub
is exported to the service locator
-
This is a ``thin'' proxy, with no processing being done on the client side
-
This is closest to the standard RPC model between client and service
Non-RMI Proxy
-
If RMI is not used, the proxy must be explicitly created
-
The client uses
FileClassifier
(like before - it
doesn't care what the proxy is)
-
The server creates a
FileClassifierImpl
and a FileClassifierProxy
-
The server exports a
FileClassifierProxy
-
The proxy and service communicate using some protocol
-
This can have processing done on both sides
-
This is good for client-server problems communicating on their own ports
with their own protocol. The proxy is the heart of the client
RMI and Non-RMI Proxies
-
You can use both RMI and a non-RMI proxy
-
The client uses
FileClassifier
-
The server creates a
FileClassifierImpl
and a FileClassifierProxy
-
The server exports a
FileClassifierProxy
and a FileClassifierImpl_Stub
-
The proxy uses the stub locally (on the client), which uses RMI
to talk back to the service
-
This can have processing done on both sides, using an RPC-like
model for communication
Jan Newmarch (http://pandonia.canberra.edu.au)
jan@ise.canberra.edu.au
Last modified: Sat Sep 4 00:14:09 EST 1999
Copyright ©Jan Newmarch