Jini grew from early work in Java to make distributed computing easier. It intends to make "network devices" and "network services" into standard components of everyone's computing environment. The computing world is currently abuzz with "service oriented systems", and Jini has been a major platform for service oriented computing since its inception, long before the term became popular.
Jini supports both software and hardware services. When you buy a new piece of office computing equipment such as a desk lamp, or a new home computer appliance such as an alarm clock, it will not only carry out its ``traditional'' functions but will also join into a network of other computer devices and services. The desk lamp will turn itself off when you leave your desk, informed by sensors in your chair; the alarm clock will tell your coffee maker to switch on a few minutes before it wakes you up. These hardware services will interact with software services such as calendar and diary services and possibly with external services such as weather and stock exchange services (to wake you up early if the weather is cold, or there is sudden movement on the market). Jini doesn't care what is behind services, but just makes them available to applications.
Homes, offices and factories are becoming increasingly networked. Current twisted pair wiring will remain, but will be augmented by wireless networks and networks built on your phone lines and power cables. On top of this will be an infrastructure to allow services to communicate. TCP/IP will be a part of this, but will not be enough. There will need to be mechanisms for service discovery, for negotiation of properties, and for event signalling (``my alarm has gone off - does anyone want to know?'').
Jini supplies this higher level of interaction. This chapter gives a brief overview of the components of a Jini system and the relationships between them.
The licensing model for Jini has now changed to an open source Apache license from a proprietary license. This change, plus the continued quality of the middleware has sparked renewed interest in 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, and clients that wish to use such a service can then locate it and call it to perform tasks. Jini can be used for mobile computing tasks where a service may only be connected to a network for a short time, but it can more generally be used in any network where there is some degree of change. There are a large number of scenarios where this would be useful:
A new printer can be connected to the network and announce its presence and capabilities. A client can then use this printer without having to be specially configured to do so.
A digital camera can be connected to the network and present a user interface that will not only allow pictures to be taken, but it can also be aware of any printers so that the pictures can be printed.
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.
New capabilities extending existing ones can be added to a running system without disrupting existing services, or without any need to reconfigure clients.
Services can announce changes of state, such as when a printer runs out of paper. Listeners, typically of an administrative nature, can watch for these changes and flag them for attention.
Jini is not an acronym for anything, and does not have a particular meaning. (though it gained a post hoc it gained an interpretation of ``Jini is not initials''.) A Jini system or federation is a collection of clients and services all communicating by the Jini protocols. Often this will consist of applications written in Java, communicating using the Java Remote Method Invocation mechanism. Although 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. Jini supplies a ``middleware'' layer to link services and clients from a variety of sources.
When you download a copy of ``Jini'', you get a mixture of things. Firstly, Jini is a specification of a set of middleware components. This includes an API (Application Programmer's Interface) so that you as a programmer can write services and components that make use of this middleware. Secondly, it includes an implementation (in pure Java) of the middleware, as a set of Java packages. By including these in the classpath of your client or service you can invoke the Jini middleware protocols to join in a Jini djinn. You also get source code to these packages as a bonus! Finally, Jini requires a number of ``standard'' services, and Sun gives basic implementations of each of these. These implementations are not an official part of ``Jini'', but are included to get you going. In practice, most users are finding these sufficient to do substantial work with Jini.
Since early days, computers have been linked in networks. The mantra from Sun Microsystems has been "the network is the computer" and this has been a cornerstone of much work in distributed computing. Based on this experience, Peter Deutsch took a critical look at the state of distributed computing in 1999 and concluded that early optimism was in many ways misplaced. Networks and applications that run on them are prone to all sorts of problems that do not occur with standalone applications, and attempts to ignore these problems just lead to unreliable and unstable applications. He identified the following fallacies of networking (extended by XXX):
The reader should be aware that Jini is only one competitor in a non-empty market. What conditions 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. Jini has been around since 1999, and while it has achieved some notable successes, it does not have the visibility of many other middleware systems. In part, this is because Jini simply works, and has been a stable but evolving platform over these years.
The Sun page http://www.sun.com/software/jini/news/success.xml lists many successful projects using Jini. This section covers a couple of them plus some other systems. For more stories, visit the web page.
Frank Sommers reports on a banking system developed by Rubean, A. G. in an article at http://www.artima.com/lejava/articles/banking_on_jiniP.html . A group of German and Swiss banks with 35,000 customers run a centralised J2EE system. However, this system needs to interact with ATM machines, cash dispensing machines and other devices linked to PCs typically through an RS232 cable. These devices have differing capabilities, their PCs are not always on and have IP addresses assigned by DHCP so that they are continually changing. This dynamic environment could be a maintenance nightmare to a centralised system. The solution by Rubean uses Jini services running on each PC, talking to the devices using the Comms API. Each service advertises itself to Jini lookup services which can handle the dynamic nature of the services without needing configuration. The J2EE system just sees collections of services and is unaware of configuration details.
Magneti Marelli Motorsport builds monitoring equipment for Formula One racing cars, and its hardware and software is used by most racing teaams. However, their software ran on proprietary platforms and lacked the flexibility and robustness they required. In the cars, sensors collect much information that is relayed by radio links to teams in the pits. The environment there is often hot and noisy, and real-time responses are needed to deal both with the data itself and with a changing environment (computers die, network cables are tripped over, etc). New software was develpoed using not only the discovery mechanisms of Jini but also its ability to self-heal the service environment. Being able to run in multiple operating system environments was also a help. The project is described at http://wiki.javapolis.com/confluence/display/JP05/Formula+One+Telemetry+with+Java
Nedap is a security management company used by over 6 million people every day. Some years ago they saw the need for a next generation of security systems and began to design one from the ground up. The heart of their system is a 64M controller with ethernet connection to the network and CAN connection to devices. Each controller exposes itself to the network as a Jini service. Examples of use include the security system controlling elevators within the Eiffel Tower in Paris. Everytime a lift comes within wireless range of a Jini lookup service, it is discovered. This allows security access of a lift to any floor to be controlled, with Jini dynamic service management handling access to services. This system is described at http://www.jini.org/meetings/eighth/J8abstracts.html#Wegman
The previous examples seem to suggest that Jini is just for linking hardware systems into software systems. Jini is certainly good at doing this, since it makes the devices appear as services, making them first class citizens in a service-oriented system. But that is not all that Jini is good for: it is a framework for service-oriented middleware, and excels in purely software-based systems too. An example is Orbitz, a multi-billion dollar online travel company, based in the US. Orbitz uses over a thousand Linux servers, and has both a changing set of machines and evolving applications running on them. For example, if a supplier is having a sale, Orbitz will allocate more services to that company. Obviously, this could be an ongoing horrific task reconfiguring applications to use new services, but Jini dynamic discovery allows this to be done transparently. In addition, services can be upgraded in place and the new versions become automatically available. Their system is described at http://www.sun.com/software/jini/news/Jini_Orbitz_Profile_Final.pdf
Orange is a major mobile communications company, with over 44 million customers worldwide. It offers a range of services, many of them supplied by external organisations. Again, this is a dynamic service environment, with new services begin deployed and existing services being revised, all in a high-volume environment. Again Jini, manages many aspects of this dynamism automatically. See http://www.sun.com/products-n-solutions/telecom/docs/orangesp_1.pdf
These systems often have to deal directly with the issues raised by the Eight Fallacies. For example, they need to work in changing topologies, unreliable networks and limited bandwidth. Jini is middleware designed to manage such issues. It is not perfect. For example, Magneti Marelli needed to tweak parts of Jini to give near real-time responses to failure instead of a default 5 minute failure time. Nevertheless, it recognises the Fallacies and gives mechanisms adequate for many systems with the possibility of sophisticated configuration for more demanding situations.
Our homes are becoming full of more and more complex pieces of electronic equipment: TVs, microwaves, hifi systems, etc, and many of these have clocks. It is almost as common to find one or more of these clocks "flashing" - particularly on the VCR. Whenever there is a power failure all the clocks start up with an incorrect time and signal this by flashing until they are manually corrected.
Many offices synchronise the clocks in a building to a central time server, but this is a luxury not allowed to most homes. But wouldn't it be nice if every clock in the house could find a correct clock and set itself? In this section we go through the steps of setting up a Jini system that will do this for some "software" clocks. No real clocks currently support Jini but it would be nice if they did!
The first step is to get the Jini classes. These are downloadable from the home page of http://www.jini.org by following the link to Jini Technology Starter Kit Downloads. This leads you to a page with several optins. You only need the Technology Starter Kit but you may like to download the examples as well.
The installation process for platforms such as Windows and Linux will check your network settings and Java installation and will start up a key component of Jini called a "registrar". Once you see a window headed "Service Browser" with a message "1 registrar, not selected" then this key component is running and you can start running some services and clients. You should see something like this:.
LaunchAll
from the installverify
directory.
At this stage there are three files in the Jini directories that you will use. They are
jsk-lib.jar
in the lib
directory contains many
of the Jini classes
jsk-platform.jar
in the lib
directory contains more
of the Jini classes
jsk-all.policy
in the installverify/support
directory. This file controls Jini security, and here just turns it off -
okay for this demonstration, not for real systems!
This book is all about how programmers can build Jini services and clients.
The flashing clocks problem has all the source code explained in Chapter 18.
But for now, you can download jar
files containing all the compiled
classes from
http://jan.netcomp.monash.edu.au/java/jini/tutorial/programs.zip .
Unzip these into any directory you want. There are three jar
files
of interest, under the dist
directory:
clock.clock.ticker.jar
clock.clock.computer.jar
clock.clock-dl.jar
These files are as follows:
clock.clock.ticker.jar
contains the class files for a standard "dumb" clock thst starts off with a random
time and just ticks away. However, it is smart enough to look around the network
to see if there are any other clocks that it can synchronise with.
clock.clock.computer.jar
is a "smarter" clock that gets its time
from the inbuilt computer clock which we assume has the correct time. This clock
also looks around the network to see of there are clocks which should synchronise
with it.
clock.clock-dl.jar
This file contains special classes that can be downloaded across the network.
Systems like CORBA and Web Services rely on getting references to remote services
and making calls using specific protocols by these references. Jini on the other
hand relies on downloading Java classes representing a service: once a client has
these classes then it just makes local calls and doesn't care how the downloaded
classes talk to the service.
When clients find services, they download a proxy for the service. Support code for this proxy
is usually in a jar
file on an HTTP server. So the file
clock.clock-dl.jar
has to be on an HTTP server somewhere. You can copy this
file to an HTTP server you have access to, or you can just use the file on the HTTP server that I run at
jan.netcomp.monash.edu.au
. (If you have a firewall between my server and your
computers then it may be easier to put the file on a local server than to get Java
to talk through the firewall. You can get away without using these classes
in this example - the clocks will work okay, but the service browser won't see the services properly.)
That's all you need to get a demonstration working. You can start up a flashing clock by running
Java from, say, a command box under Windows or a terminal window under Unix.
You will need to set your classpath so that it contains the Jini files
jsk-platform.jar
and jsk-lib.jar
,
and also the clock file clock.clock.ticker.jar
.
For example, under Unix you could run
JINI_HOME=...
CLOCK_DIR=...
CLASSPATH=$JINI_HOME/lib/jsk-lib.jar:$JINI_HOME/lib/jsk-platform.jar:$CLOCK_DIR/clock.clock.ticker.jar
export CLASSPATH
and under Windows
set JINI_HOME = ...
set CLASSPATH = %JINI_HOME%/lib/jsk-lib.jar;%JINI_HOME%/lib/jsk-platform.jar;%CLOCK_DIR%/clock.clock.ticker.jar
After setting the classpath, run a dumb ticking clock under Linux by
java \
-Djava.rmi.server.codebase=http://jan.netcomp.monash.edu.au/classes/clock.clock-dl.jar \
-Djava.security.policy=$JINI_HOME/installverify/support/jsk-all.policy \
clock.clock.TickerClock \
"Ticking Clock"
and under Windows by
java \
-Djava.rmi.server.codebase=http://jan.netcomp.monash.edu.au/classes/clock.clock-dl.jar \
-Djava.security.policy=%JINI_HOME%/installverify/support/jsk-all.policy \
clock.clock.TickerClock \
"Ticking Clock"
The first parameter (codebase) lets the service tell clients where the downloadable files are;
the second parameter (security) sets the policy for what remote code is allowed to do to this
service; the third parameter is the main
class file; the last parameter is just
a string to be displayed as window title.
You should see a clock such as this, flashing every second
You can run this command as often as you want, on the same or different machines. Each one should start up a new flashing clock. These clocks will all discover one another, but since none of them shows a valid time there is nothing that they can do to each other.
Now start up a "smart" clock that is showing the right time. The classpath needs to be
set to the Jini files jsk-platform.jar
and jsk-lib.jar
again,
but this time should include clock.clock.computer.jar
instead of
clock.clock.ticker.jar
.
The you run the good clock by
java \
-Djava.rmi.server.codebase=http://jan.netcomp.monash.edu.au/classes/clock.clock-dl.jar \
-Djava.security.policy=JINI_HOME/installverify/support/jsk-all.policy \
clock.clock.ComputerClock \
"Computer Clock"
As this one starts up, it will discover the other clocks and they will discover it. The wrong clocks will ask the right clocks for the correct time; the right clocks will tell the wrong clocks to reset their time. This is a peer-to-peer system, and I don't know whether right tells wrong or wrong get from right - it doesn't matter. All that matters is that the correct time will soon show on all clocks. Later, the clocks will "drift", but after reading Chapter 18 you will easily be able to add code to re-synchronise on a regular basis.
If you now start up another possible flashing clock, it will quickly discover the other correct clocks and may not even flash at all.
What is going on with these clocks that is valuable to a distributed application's programmer?
Finally in this section, we look at pseudocode for the clocks.
main:
allow remote code to be downloaded and run within this VM
start a thread to asynchronously discover proxies for clock services,
calling us as listener
service discovered:
if we are invalid and the remote clock is valid
set our time from the remote clock
set state to valid
else if we are valid and the remote clock is invalid
set the time on the remote clock
That's it! The rest of the clocks code (less than 700 lines total) is the service specification,
user interface classes and keeping the clocks ticking.
Jini is just one of a large number of distributed systems architectures, including industry-pervasive systems such as CORBA, DCOM and more recently Web Services. It is distinguished by paying particular attention to the Eight Fallacies and dealing with these issues rather than ignoring them. In addition, it is based on Java, and deriving many features purely from this Java basis. One of the later chapters discusses bridging between Jini and CORBA, as an example of linking these different distributed architectures.
There are many other middleware systems. Each of them is designed for a particular domain of application. Universal Plug 'n Play (UPnP) is designed for a world of devices such as light switches and alarm systems. It does not deal with services in general, such as software services. Web Services are intended to cover the space of long-lived stable services with fixed addresses and do not handle transient services well. Jini is designed for networks in which failure may occur, or where services and clients have a more volatile nature.
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 which acts as a broker/trader/locator between services and clients (The generic term for this seems to be settling on service cache manager). 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.) See figure 1.1.
Code will be moved around between these three pieces, and this is done by marshalling the objects. This involves serializing the objects in such a way that they can be moved around the network, stored in this "freeze-dried" form, and later reconstituted by using included information about the class files as well as instance data. This is done 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. Often this will be done using RMI (Remote Method Invocation), although the Jini specification does not require this and there are many other possibilities.
A service is a logical concept such as a blender, a chat service, a disk. It will turn out to be usually defined by a Java interface, and commonly the service itself will be identified by this interface. Each service can be implemented in many ways, by many different vendors. For example, there may be Joe's dating service, Mary's dating service or many others. What makes them the "same" service is that they implement the same interface; what distinguishes one from another is that each different implementation uses a different set of objects (or maybe just one object) belonging to different classes.
A service is created by a service provider. A service provider plays a number of roles:
It creates the objects that implement the service
It registers one of these - the service object with lookup services. The service object is the "publically visible" part of the service, and will be downloaded to clients
It stays alive in a server role, performing various tasks such as keeping the service "alive".
In order for the service provider to register the service object with a lookup service, the server must first find the lookup service. This can be done in two ways: if the location of the lookup service is known, then the service provider can use unicast TCP to connect directly to it. If the location is not known, the service provider will make UDP multicast requests, and lookup services may respond to these requests. Lookup services will be listening on port 4160 for both the unicast and multicast requests. (4160 is the decimal representation of hexadecimal (CAFE - BABE). Oh well, these numbers have to come from somewhere.) 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 service provider 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 service provider does with the registrar is to register the service with the lookup service. This involves taking a copy of the service object, and storing it on the lookup service as in figures 1.2, 1.3 and 1.4.
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 object to be copied across to it. See figures 1.5, 1.6, 1.7, and 1.8.
At this stage there is the original service object running back on its host. There is a copy of the service object stored in the lookup service, and there is a copy of the service object running in the client's JVM. The client can make requests of the service object running in its own JVM.
Some services can be implemented by a single object, the service object. How does this work if the service is actually a toaster, a printer, or controlling some piece of hardware? By the time the service object runs in the client's JVM, it may be a long way away from its hardware. It cannot control this remote piece of hardware all by itself. In this case, the implementation of the service must be made up of at least two objects, one running in the client and another distinct one running in the service provider.
The service object is really a proxy, which will communicate back to other objects in the service provider, probably using RMI. The proxy is the part of the service that is visible to clients, but its function will be to pass method calls back to the rest of the objects that form the total implementation of the service. There isn't a standard nomenclature for these server-side implementation objects. I shall refer to them in this book as the "service backend" objects.
The motivation for discussing proxies is when a service object needs to control a remote piece of hardware that is not directly accessible to the service object. However, it need not be hardware: there could be files accessible to the service provider that are not available to objects running in clients. There could be applications local to the service provider that are useful in implementing the service. Or it could simply be easier to program the service in ways that involve objects on the service provider, with the service object being just a proxy. The majority of service implementations end up with the service object being just a proxy to service backend objects, and it is quite common to see the service object being referred to as a service proxy. It is sometimes referred to a the service proxy even if the implementation doesn't use a proxy at all!
The proxy needs to communicate with other objects in the service provider. It appears we have a chicken-and-egg situation: how does the proxy find the service backend objects in its service provider? Use a Jini lookup? No, when the proxy is created it is "primed" with its own service provider's location so that when run it can find its own "home". This will appear as in figure 1.9
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.
package nonworking;
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.
package nonworking;
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 figure
1.10
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
have a simple interface
are useful in more than one situation
can be replaced or varied
If the application is re-organised as a collection of services, then it could look like figure 1.11
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 Java code running in Java Virtual
Machines (JVM). The implementation may be in pure Java but it
could make use of native code by JNI (Java Native Interface) or
make external calls to other applications. Often, each of these
applications will run in its own JVM on its own computer, though
they could run on the same machine or even share the same JVM.
When they run, they will need access to Java class files, just
like any other Java application. Each component will use the
CLASSPATH
environment variable or use the
classpath
option to the runtime to locate the classes
it needs to run.
However, Jini also 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 one of the places where a distributed Jini application differs from many other distributed systems: 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 provider 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.
These files and support services are shown in figure 1.12
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
.
Client-server systems built from scratch typically require the design of a communications protocol. For example, before the web could became as important as it is today, the "hyper-text transport protocol" HTTP had to be designed so that clients and servers could communicate. This protocol has been through several public versions: 0.9, 1.0 and 1.1. Clients and servers have had to be rebuilt on each version change of even this simple procotol
RPC systems such as Sun's ONC, CORBA, COM+ and more recently SOAP also rely on a fixed protocol. In these cases though, there are usually tools which will generate code to manage the protocol messaging. However, these tools need to generate two sets of code: one for the client-side and one for the server-side. Any change to the protocol means that both client and server have to have this code regenerated.
This dependence on protocol is tightly bound to how clients address services, which depends on how they find these services. For example, to address a Web service you often need a WSDL document which contains the URL of the service's server and method names of the service. Coupled with knowledge that the service is addressed using SOAP, a client can then talk to it. With CORBA, in a variety of ways you could obtain an object reference (through a name server, using "stringified" references or through a trader). Given this reference and the knowledge that CORBA uses the IIOP protocol, a client could then talk to a server.
Protocol changes are a nightmare once it has become a popular system. It took
years for all clients and servers to upgrade to HTTP 1.1
and similarly for CORBA protocol changes.
Some protocols such as that used by sendmail
haven't been touched
for years because of the chaos to email that would almost
certainly result in any changes, even though
many people think it is well past its use-by date.
When you discover a Jini service, you don't get an address to be dealt with by a particular protocol. Instead you get a Java proxy object with known methods. This alters the playing field in a significant way: the client doesn't need to know the communications protocol at all! It just makes local method calls on the proxy.
The proxy comes from the server, and this is key to client ignorance. The client doesn't know the protocol used between proxy and service since it never has to know. The communications protocol is private to the proxy and the service. That means that the proxy and the service can use any protocol they wish, and it has no effect on the client at all. The proxy and service can change the protocol, and the client never knows.
There is often an assumption that Jini systems must be "all Java". This isn't quite true. Certainly the client has to be a Java client, although even here there are caveats: strictly, the client must be able to invoke a Java object through a Java Virtual Machine and there are many languages that can now do this. The proxy needs to be JVM bytecodes. Most likely this will be generated from Java source code, but not necessarily. But on the service side, who knows? The proxy can talk to any service it wants to, using any protocol it has chosen. For example, many people (including the author) have built proxies that will talk SOAP to UPnP devices or Web Services. The client is ignorant of the service language and has no need to care.
It isn't quite the "end of protocols" unfortunately. Jini leads to the end of client knowledge of invocation protocols, but the client still has to discover the Jini proxy. There is still a discovery protocol involved. However, the Jini discovery protocol is fairly lightweight and is customised to just this task rather than being a general-purpose protocol. Jini discovery involves a simple protocol to discover a lookup service and then a mechanism for downloading bytecodes. In the last section we pointed out the use of an HTTP server to deliver these proxy bytecodes, but this is not a prescribed mechanism for Jini. It would be possible to use other mechanisms such as email or ftp, although I don't think anyone has yet seriously considered doing this since HTTP seems to be good enough so far.
A Jini system is made up of three parts
Service
Client
Service locator
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.
If you found this chapter of value, the full book "Foundations of Jini 2 Programming" is available from APress or Amazon .
This work is licensed under a
Creative Commons License, the replacement for the earlier Open Content License.