New to Java? We'll help you get started with our revised beginner's tutorial, or our free online textbook.
|
Get the latest Java books |
|
h t t p : / /w w w . j a v a c o f f e e b r e a k . c
o m /
|
Contents
This chapter gives a brief overview of the components of a Jini system and the relationships between them.
Jini is the name for a distributed computing environment, that can offer ``network plug and play''. A device or a software service can be connected to a network and announce its presence. Clients that wish to use such a service can then locate it and call it to perform tasks. This can be used for mobile computing tasks where a service is only connected to a network for a short time, but more generally can be used in any network where there is some degree of change. There are a large number of scenarios where this can be used
Jini is not an acronym for anything, and does not have a particular meaning. A Jini system or federation is a collection of clients and services all communicating by the Jini protocols. Normally this will consist of applications written in Java, communicating using the Java Remote Method Invocation mechanism. While Jini is written in pure Java, neither clients nor services are constrained to be in pure Java. They may include native code methods, act as wrappers around non-Java objects, or even be written in some other language altogether. They just need to talk the Jini protocols. This gives a Jini federation a flexibility beyond Java, in which the framework is supplied using simple Java mechanisms, but can link services and clients from a variety of sources.
Jini is just one of a large number of distributed systems architectures, including industry-pervasive systems such as CORBA and DCOM. It is distinguished by being based on Java, and deriving many features purely from this Java basis. There are other Java frameworks from Sun which would appear to overlap Jini, such as Enterprise Java Beans. This book does not delve much into the relationships between all these various systems, but the reader should be aware that Jini is only one competitor in a non-empty market. What will condition the success or failure of Jini is partly the politics of the market, but also (hopefully!) the technical capabilities of Jini, and this book will deal with some of the technical issues involved in using Jini.
In a running Jini system, there are three main players. There is a service, such as a printer, a toaster, a marriage agency, etc. There is a client which would like to make use of this service. Thirdly, there is a lookup service (service locator) which acts as a broker/trader/locator between services and clients. There is an additional component, and that is a network connecting all three of these, and this network will generally be running TCP/IP. (The Jini specification is fairly independent of network protocol, but the only current implementation is on TCP/IP.)
Code will be moved around between these three pieces, and this is done by serializing the objects (and marshalling them to allow storage without reconstitution), and using Java's socket support to send and receive objects. In addition, objects in one JVM (Java Virtual Machine) may need to invoke methods on an object in another JVM and this will typically be done using RMI (Remote Method Invocation), although the Jini specification does not require this (it may require RMI semantics, but not necessarily implementation).
A service will actually be an object (or set of objects) which is living within a server. The server performs various tasks on behalf of the service. The first stage is for the server to register the service with the lookup service/service locator. In order to peform this registration, the server must first find a lookup service. This can be done in two ways: if the location of the lookup service is known, then the server can use unicast TCP to connect directly to it. If the location is not known, the server will make UDP multicast requests, and lookup services will respond to these requests. Lookup services will be listening on port 4160 for both the unicast and multicast requests. When the lookup service gets a request on this port, it sends an object back to the server. This object, known as a registrar, acts as a proxy to the lookup service, and runs in the service's JVM (Java Virtual Machine). Any requests that the server needs to make of the lookup service are made through this proxy registrar. Any suitable protocol may be used to do this, but in practice the implementations that you get of the lookup service (e.g from Sun) will probably use RMI.
What the server does with the registrar is to register the service with the lookup service. This involves taking a copy of the service, and storing it on the lookup:
The client on the other hand, is trying to get a copy of the service into its own JVM. It goes through the same mechanism to get a registrar from the lookup service. But this time it does something different with this, which is to request the service to be copied across to it.
At this stage there is the original service running back on its host. There is a copy of the service stored in the lookup service, and there is a copy of the service running in the client's JVM. The client can make requests of the service object running in its own JVM.
How does this work if the service is actually a toaster, a printer, or controlling some piece of hardware? By the time it runs in the client's JVM, it may be a long way away from its hardware. In this case, rather than sending out a copy of the service itself, the service will send out a proxy, which will communicate back to the service, probably using RMI. It appears we have a chicken-and-egg situation: how does the proxy find its service? Use a Jini lookup? No, when the proxy is created it is ``primed'' with its own service's location so that when run it can find its own ``home''. This will look like
How is the proxy primed? This isn't specified by Jini, and can be done
in a large number of ways. For example, an RMI naming service can be used
such as rmiregistry
, where the proxy is given the name of
the service. This isn't very common, as RMI proxies can be passed more
directly as returned objects from method calls,
and these can refer to ordinary RMI server objects or to
RMI activatable objects. Or the proxy can be implemented without
any direct use of RMI, and can then use an RMI exported service or some other
protocol altogether such as ftp, http or a home-grown protocol. These various
possibilities are all illustrated in later chapters.
Internally a client will look like
Pseudocode | Where discussed |
---|---|
prepare for discovery
|
Discovering a lookup service |
discover a lookup service
|
Discovering a lookup service |
prepare a template for lookup search
|
Entry objects and Client search |
lookup a service
|
Client search |
call the service
|
The following code is simplified from the real case, by omitting various checks
on exceptions and other conditions.
It attempts to find a FileClassifier
service, and then calls the method
getMIMEType()
on this service.
The full version is given in a later chapter.
We don't give detailed explanations right now, this is just to show how the
above schema translates into actual code.
public class TestUnicastFileClassifier {
public static void main(String argv[]) {
new TestUnicastFileClassifier();
}
public TestUnicastFileClassifier() {
LookupLocator lookup = null;
ServiceRegistrar registrar = null;
FileClassifier classifier = null;
// Prepare for discovery
lookup = new LookupLocator("jini://www.all_about_files.com");
// Discover a lookup service
// This uses the synchronous unicast protocol
registrar = lookup.getRegistrar();
// Prepare a template for lookup search
Class[] classes = new Class[] {FileClassifier.class};
ServiceTemplate template = new ServiceTemplate(null, classes, null);
// Lookup a service
classifier = (FileClassifier) registrar.lookup(template);
// Call the service
MIMEType type;
type = classifier.getMIMEType("file1.txt");
System.out.println("Type is " + type.toString());
}
} // TestUnicastFileClassifier
A server application will internally look like
Pseudocode | Where discussed |
---|---|
prepare for discovery
|
Discovering a lookup service |
discover a lookup service
|
Discovering a lookup service |
create information about a service
|
Entry objects |
export a service
|
Service registration |
renew leasing periodically
|
Leasing |
The following code is simplified from the real case, by omitting various checks
on exceptions and other conditions.
It exports an implementation of a file classifier service, as a
FileClassifierImpl
object.
The full version is given in a later chapter.
We don't give detailed explanations right now, this is just to show how the
above schema translates into actual code.
public class FileClassifierServer implements DiscoveryListener {
protected LeaseRenewalManager leaseManager = new LeaseRenewalManager();
public static void main(String argv[]) {
new FileClassifierServer();
// keep server running (almost) forever to
// - allow time for locator discovery and
// - keep re-registering the lease
Thread.currentThread().sleep(Lease.FOREVER);
}
public FileClassifierServer() {
LookupDiscovery discover = null;
// Prepare for discovery - empty here
// Discover a lookup service
// This uses the asynchronous multicast protocol,
// which calls back into the discovered() method
discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);
discover.addDiscoveryListener(this);
}
public void discovered(DiscoveryEvent evt) {
ServiceRegistrar registrar = evt.getRegistrars()[0];
// At this point we have discovered a lookup service
// Create information about a service
ServiceItem item = new ServiceItem(null,
new FileClassifierImpl(),
null);
// Export a service
ServiceRegistration reg = registrar.register(item, Lease.FOREVER);
// Renew leasing
leaseManager.renewUntil(reg.getLease(), Lease.FOREVER, this);
}
} // FileClassifierServer
Jini uses a ``service'' view of applications. This is in contrast to the simple object-oriented view of an application. Of course, a Jini ``application'' will be made up of objects, but these will be distributed out into individual services, which will communicate via their proxy objects. The Jini specification claims that in many monolithic applications there are one or more services waiting to be released, and making them into services increases their possible uses.
To see this, we can look at a ``smart file viewer''. This is an application that
will be given a filename, and based on the structure of the name will decide
what type of file it is (.rtf
is Rich Text Format, .gif
is a GIF file, and so on). Using this classification it will then call up
an appropriate viewer for that type of file, such as an image viewer or document
viewer. A UML class diagram for this might look like
There are a number of services in this. Classifying a file into types is one (which will be used heavily in the sequel - because it is simple). This service can be used in lots of different situations, not just viewing contents. Each of the different viewer classes is another. This is not to say that every class should become a service! That would be overkill. What makes these qualify as services is that they
If the application is re-organised as a collection of services, then it could look like
Each service may be running on a different machine on the network (or on the same
machine - it doesn't matter). Each exports a proxy to whatever service locators are
running. The SmartViewer
application finds and downloads whatever
services it needs, as it needs them.
The three components of a Jini system are clients, services and service
locators, which may run anywhere on the network. These will be implemented
using standard Java code, and will run in Java Virtual Machines (JVM). Typically,
each of these applications will run in a single JVM, although there are techniques
available to run multiple Java applications in the same JVM. When they run,
they will need access to Java class files, just like any other Java
application.
An application can use the CLASSPATH
environment variable
or use the classpath
option to the runtime to locate these
classes.
However, Jini relies heavily on the ability to move objects across the network, from one JVM to another. In order to do this, particular implementations must make use of support services such as RMI daemons and HTTP (or other) servers. The particular support services required depend on implementation details, and so may vary from one Jini component to another.
A Java object running as a service has a proxy component exported to the service locators and then onto a client. It passes through one JVM in ``passive'' form and is activated ( brought to life) in the client's JVM. Essentially, a ``snapshot'' of the object's state is taken using serialization, and this snaphot is moved around. An object consists of both code and data, and it cannot be reconstituted from just its data - the code is also required. Where is the code? This is where a distributed Jini application differs from an ordinary one: the code is not likely to be on the client side. If it was required to be on the client side, then Jini would lose almost all of its flexibility because it wouldn't be possible to just add new devices and their code to a network. The class definitions are most likely on the server, or perhaps on the vendor's home Web site.
So class definitions for service proxy objects must also be downloaded,
usually from where the service came from. This could be done using a variety
of methods, but most commonly an HTTP or FTP protocol is used.
The service specifies the protocol used and also the location of the class
files using the java.rmi.server.codebase
property.
The object's serialized data contains this codebase, which is used by
the client to access the class files.
If the codebase specifies an HTTP url, then there must be an HTTP server
running at that url, and the class files must be there also. This often
means one HTTP server per service, but this isn't required: a set of services
could make their class files available from a single HTTP server, and this server
could be running on a different machine to the services. This gives two sets of
class files: the set needed to run the service (specified by
CLASSPATH
) and the set needed to reconstitute objects at the client
(specified by the codebase
property).
For example, the mahalo
service supplied by Sun as a transaction
manager uses the class files in mahalo.jar
to run the service,
and the class files in mahalo-dl.jar
to reconstitute the
transaction manager proxy at the client.
To run mahalo
, the CLASSPATH
must include
mahalo.jar
, and to reconstitute its proxy on a client,
the codebase
property must be set to mahalo-dl.jar
.
A proxy service gets exported to the client. In most cases this will need to communicate
back to its host service. There are many ways to do this. One mechanism is the Java
Remote Method Invocation (RMI) system. This comes in two flavours in JDK 1.2:
the original UnicastRemoteObject
and the newer Activable
class. Whereas UnicastRemoteObject
requires a process to remain
alive and running, Activable
objects can be stored in a passive
state and the Activation system will create a new JVM if needed when a method call
is made on the object. While passive, an activatable object will need to be
stored on some server, and this server must be one which can accept method calls
and activate the objects. Sun supply such a server, called rmid
.
This is real, real obscure and deep stuff if you are new to RMI or even to the
changes it is going through. So why is it needed? Sun supply a service locator
called reggie
, and this is really just another Jini service that
plays a special role. In particular, it exports proxy objects - the
registrar
objects. What makes this complex is that
reggie
uses Activable
in its implementation. In order to run reggie
, you first have to
start an rmid
server on the same machine,
and then reggie
will register with it.
This isn't all downhill: running rmid
has beneficial side-effects.
It maintains log files of its own state, which includes the activable objects
it is storing. So reggie
can crash or terminate, and
rmid
will restore it as needed. Indeed, even rmid
can crash or be terminated, and it will use its log files to restore state
so that it can still accept calls for reggie
objects.
A Jini system is made up of three parts
registrar
acts as a proxy to the lookup locator, and runs on both the client
and service.
A service and a client both possess a certain structure, which is detailed in the following chapters. Services may require support from other non-Jini servers, such as an HTTp server.
Copyright 1998, 1999, 2000 David Reilly
|
Privacy | Legal | Linking | Advertise! |
Last updated:
Monday, June 05, 2006
|