Service (JavaSpaces).
There are two JavaSpaces clients in this example: one client displays a
raytraced scene of four spheres and the other client computes the scene
by performing raytracing.
NOTE: This example works with Jini 1.x technology. Please
see the ex2 example for a version that works with
Jini 2.x.
The raytrace client
A picture of the raytrace client appears below.
The Chunk: data entry areas in the upper left corner of the window
allow you to specify how large each chunk of the image should be. The
worker task (which computes the image using raytracing) will produce pieces
of the whole picture sized as specified by the chunk values. For
example, if you were to choose chunks of 100x100 then each
piece of the picture produced by the worker task would be 100 by 100 pixels
in size.
The worker client
A picture of the worker client appers below. The worker client shows the
name of the machine it is running on ("tibook" in this case) and the name
of the JavaSpaces service it is communicating with ("JavaSpaces" in this
case). When the worker is receiving tasks and computing the portions of
the image for the raytrace client information is printed in the area
below the buttons Start, Stop, and
Cancel.
The processes
This is a distributed application in that several programs work together
to produce the results. Below is an overview of the programs involved.
- Reggie A Jini lookup service. Jini services and the clients
which use them must be able to locate each other. The lookup service
provides the means by which services can advertise their presence and
clients can select services based on the interfaces that these
services implement.
- Outrigger A services that implements the JavaSpace
interface. This service will registers lookup service and will
be utilized by the two client programs raytrace and
worker
- Code servers Jini takes advantage of the Java Programming
Language's ability to load code (class files) associated with a
class dynamically. Code servers provide an easy means to make
these class files available. There will be more explaination
of this below.
- raytrace This is the program that displays the raytraced
scene as described above.
- genericWorker This is the worker program described
above. The raytrace program creates work assignments for this
process. This process takes those assignments, completes them,
and returns the results back to the raytrace application.
Precisely how this happens is described below.
- rmid This is the RMI Activation daemon used by
Reggie and other services in the Jini Network Technology
Starter Kit (JSK) version 1.2.1 and earlier.
Moving code makes Jini work
The Java Programming Language provides a convenient mechanism for bundling
up all of the class files necessary to run a given program into one file
called a JAR. For example, the program Reggie can be run easily
from the JAR file provided in the JSK called reggie.jar.
JAR files can also be used when you wish to share a class's implementation
with a program that only knows of the interface that class implements or
only knows about that class's superclass. Examine the diagram below.
In the above diagram, the code server supplies classes out of the
program1-dl.jar JAR file. Program2 gets serialized
objects from Program1 and although Program2 does not have
any explicit knowledge of these type (which were possibly developed long
after Program2 was deployed!) Program2 is able to
reconstitute these types from their serialized form because the class
files for types C1 and C2 were made available by the
code server.
Loading proxies
The picture below illustrates the various processes involved
(except rmid which was omitted). Additionally, the
code servers used to provide the class files to
other processes is also depicted along with the JAR files
needed to successfully run this example.
Proxies are likely to be types like C1 and C2 from the
previous diagram: they are defined and implemented outside of the
program which must use them. For example, when a client obtains
the proxy for Outrigger it gets a class which implements the
net.jini.space.JavaSpace interface. The client knows about
the interface net.jini.space.JavaSpace but most likely does
not know about the specific type supplied as the
Outrigger proxy.
There are several proxies that are loaded as the
raytrace example begins to execute. Outrigger,
for example, will discover the lookup service and load
its proxy. Once the lookup service's proxy has been loaded
Outrigger will use this proxy to register its own proxy for
others to use.
The raytrace client program looks for a service which implements
net.jini.space.JavaSpace. The client first discovers a
lookup service, obtains the lookup service's proxy, then uses the
lookup service's proxy to locate another service which implements
net.jini.space.JavaSpace. That service
will be Outrigger as described above. The other
services and clients go through similar discovery, lookup,
and proxy loading exercises.
Running raytrace
The raytrace example can be easily run by locating the
bin12 directory and running the run_allray1.sh
script on a Unix system such as Solaris from Sun Microsystems.
This script invokes following:
run_rmid.sh&
jini_codeserver.sh&
app_codeserver.sh&
run_reggie.sh&
run_mahalo.sh&
run_outrigger.sh&
run_worker1.sh&
run_trace1.sh&
When the user interface for the raytrace Applet appears, enter values
for Chunk such as 100 x 100 and press the Start
button. This will begin the process of writing tasks to the JavaSpace for the
worker to pick up.
The tasks written are subclasses of the type TaskEntry defined
in the genericWorker package. The worker picks up these
entries from the JavaSpace and calls the execute method. Note
that the subtype of TaskEntry called RenderTask
is defined in the raytrace package. The worker knows only about
the type TaskEntry and not about its subclass
RenderTask. Even so, since trace-dl.jar
contains the definition for RenderTask and objects written to
the JavaSpace are annotated with a codebase that refers to a class server
offering classes in trace-dl.jar the worker program
is able to load objects of these types, call the execute
method, and successfully render our picture with code supplied by
the trace package.
When the raytrace example is running portions of the picture
are displayed as they are completed by the worker task. Below is
a snapshot of the raytrace window during execution. In this
image, about one fourth of the imaging tasks have completed.
Completed raytrace
Eventually, the worker task will take the
last RenderTask entry from the JavaSpace and produce
the final section of the image. The picture below shows the
raytrace window with the completed scene of four spheres.
Where to go from here
This example illustrates how a simple relationship between a
genericWorker and an application such as a
raytrace program can be used to offload work in a distributed
system. Try adding more worker processes. More worker
processes should be able to render the picture more quickly assuming
sufficient resources are available.
Jini Network Technology is designed to assist in distributed systems.
If you ran all of the programs on one machine, try moving some of
the programs to different machines. For example, run each
worker on a different machine. Since the code is either in
the application's JAR file or downloaded via a codeserver the location
of a worker should be irrelevant (assuming satisfactory
network connectivity and visibility to the other resources such as
the lookup service, etc.).
Finally, this example makes some simplifying assumptions about
reliability. For example, if a worker were to take a
TaskEntry and then abort suddenly, that assignment
would be lost. Integration of the Transaction Manager
can help ensure that the application recovers from such failures.
Copyright © 2003 Sun Microsystems, Inc. All Rights Reserved.