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 /

Java Coffee Break

Chapter 1: Overview of Jini

Contents

This chapter gives a brief overview of the components of a Jini system and the relationships between them.

1.1. Jini

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

  1. A new printer connected to the network can announce its presence and capabilities. A client can then use this printer without having to be specially configured to do so.
  2. A digital camera can be connected to the network. It can present a user interface that will not only allow pictures to be taken, but is also aware of any printers so that the pictures can be printed if possible.
  3. A configuration file that is copied and modified on individual machines can be made into a network service from a single machine, reducing maintenance costs.
  4. New capabilities extending existing ones can be added to a running system without disruption of existing services, or any need to reconfigure possible clients
  5. Services can announce changes of state, such as a printer running out of paper. Listeners, typically of an administrative nature, can watch for these and flag them for attention

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.

1.2. Components

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).

Figure 1.1: Components of a Jini system

1.3. Service Registration

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:

Figure 1.2: Querying for a service locator
Figure 1.3: Registrar returned
Figure 1.4: Service uploaded

1.4. Client 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.

Figure 1.5: Querying for a service locator
Figure 1.6: Registrar returned
Figure 1.7: Asking for a service
Figure 1.8: Service returned

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.

1.5. Proxies

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

Figure 1.9: A proxy service

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.

1.6. Client Structure

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

1.7. Server Structure

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

1.8. Partitioning an Application

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

Figure 1.10: UML diagram for an application

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

  1. have a simple interface
  2. are useful in more than one situation
  3. can be replaced or varied
They are reusable, and this is makes them good candidates for services. They do not require high-bandwidth communication (such as a stack would), and are not completely trivial.

If the application is re-organised as a collection of services, then it could look like

Figure 1.11: Application as a collecetion of services
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.

1.9. Support Services

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.

1.9.1 HTTP server

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.

Figure 1.12: Support services for mahalo

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.

1.9.2 RMI daemon

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.

1.10. Summary

A Jini system is made up of three parts

  1. Service
  2. Client
  3. Service locator
Code is moved between these applications. A 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.


This file is Copyright (©) 1999, 2000 by Jan Newmarch (http://pandonia.canberra.edu.au) jan@ise.canberra.edu.au.
This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v0.4 or later (the latest version is presently available at http://www.opencontent.org/openpub/). Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.

Back to main


Copyright 1998, 1999, 2000 David Reilly

Privacy | Legal | Linking | Advertise!

Last updated: Monday, June 05, 2006