-
Jini objects are moved in ``marshalled'' form
-
Class files may need to follow these for proper activation
-
The class files may need to be available from HTTP servers
-
Services may use RMI Activation and may need to have rmid running
-
Security permissions will need to be set using JDK 1.2
security model
Proxies
-
A toaster will be controlled by some service software
-
The service software will be moved across the network to the client
-
The mobile code must be a proxy for the real service code
-
The proxy may be explicitly written or be an RMI proxy stub
-
Remote calls from the proxy may be RMI Remote calls, or by some
other mechanism such as private TCP connection
Attribute Registration
-
A service is uploaded to a locator as an instance of a class
-
Additional information such as address may also be uploaded
as instances of Entry classes
-
Service registration is done using a leasing system
Service Location
-
A client asks for a service as an instance of a class,
typically of an interface
-
A client may ask for additional Entry attributes
-
Matching on fields is exact
-
You can ask for a printer with a certain speed, but not for
one greater than a certain speed
-
Additional services may be used if complex boolean expressions
are needed
Leasing
-
Because services can come and go, network connections can be lost, etc,
a distributed garbage collection mechanism is needed
-
Services which register are granted a lease
-
Registration lasts for as long as the lease
-
When the lease expires, the service is removed
-
Leases can be renewed
Events
-
Jini supports a remote event model
-
Remote event listeners are registered with event sources
-
The listeners are leased, so have to keep renewing the lease
or can be discarded from the listener list
-
Jini has no support for listener lists, or for
handling leases in the list
-
A service typically exports a proxy to represent it remotely;
an event listener is typically a proxy for the real listener
GUI
-
A service can have attributes that give more information than
just the class
-
The attibutes are objects, and so can have behaviour
as well as state
-
i.e. an attribute can do more than just be useful in a comparison:
it can carry executable code that can run on the client
-
The service is represented by the service proxy.
Possible GUIs to handle the proxy can be placed in attributes
-
This can be used to customise the GUI
-
Multiple GUIs can be carried each in a different attribute
-
Different types of client may have different GUI
capabilities (AWT, Swing, MIDP UI, none)
-
The client only needs to load classes for UI objects
it can deal with
Transactions
-
Jini supports distributed transactions
-
It has a Transaction Manager with operations
Jini echo
Echo service done in Jini
The source files are here
Echo interface
Echo interface implementation
Echo server
Echo client
Compiling/running the example
-
Run a reggie server
-
All the source code is available from
here . This includes an ant
build.xml
file.
-
You can use this to build/run the examples by
ant compile
ant runserver
ant runclient
-
If you don't want to do it this way, you can run any Java compiler/runtime or IDE with
the classpath set to include the files
${jini_home}/lib/jini-core.jar
${jini_home}/lib/jini-ext.jar
${jini_home}/lib/sun-util.jar
These files are in the Jini 2.0 zip file at
ftp://jan.newmarch.name/pub/jini-1_2_1-src.zip
-
Compile looks like
javac -classpath=... SourceFile
-
At runtime you also need to specify a security policy file to overcome the "sandbox"
security model. A totally open policy is in the file
policy.all
with contents
grant {
permission java.security.AllPermission "", "";
};
-
The policy file is set by the define
-Djava.security.policy="policy file"
-
You need to compile RMI stubs for the classes that will be sent to remote systems
rmic -v1.2 server.EchoImpl
-
If you are running in a distributed system, you also need to make the Stub classes
available on an HTTP server. (You can omit this if you are running everything
on the same computer)
copy server/EchoImpl_Stub.class HTTP_server_root/classes
-
If you are running in a distributed system, you need to specify this HTTP
server by the define
-Djava.rmi.server.codebase=http://${hostname}/classes/
.
-
Run looks like
java -classpath=... -Djava.rmi.server.codebase=... -Djava.security.policy=... ClassFile
Flashing clocks in Jini
-
This is a Jini version of the flashing clocks problem
-
There is no need for a Java-XML data-type conversion class: Jini
can send Java objects across the network.
-
There is no need for a "device". It is replaced by a server which just
creates and exports the service.
-
Method calls to remote objects have to catch potential
RemoteException
Java classes for timer service
Code is available from
here
Timer service
-
This must be described by a Java interface. This is the only
description of the service, there is no separate XML document
-
The interface should extend
Remote
and all methods
must throw a RemoteException
-
The standard java class
java.util.Date
is used
Computer Timer
Implementation of timer that gets its time from the computer clock using the Calendar class.
This is the same as the UPnP service, except it uses java.util.Date
Ticker Timer
Another implementation that runs a "ticker" in a thread to update the time.
This timer is invalid until something else sets its time.
This is the same as the UPnP service
Clock device
-
This is just a server to create this service and to handle interactions with the
rest of the system. I have called it a "device" just to make it look similar to the
UPnP version
-
It registers the service (not the device) with lookup services
by using a
JoinManager
-
Clients make method calls directly on the service after discovering the service.
There is no need to set up an "action" listener and handle calls - this is done
by the Jini system
-
The "device" can monitor other services by listening to events from a
ServiceDiscoveryManager
-
Changes to other services are handled in
serviceAdded()
, etc.
The "device" can make method calls on the remote services and also to its
own local service
-
Method calls on remote services have to catch
RemoteException
Ticker clock
This creates a clock device, sets a ticker timer in it and starts the frame.
This is basically the same as the UPnP version except in doesn't have to catch
the parse error for the XML device description.
Computer clock
This creates a clock device, sets a computer timer in it and starts the frame .
Similar to the UPnP version
Clock frame
This is the same as the UPnP version
Clock pane
This is like the UPnP version, but calls to remote objects have to catch a potential
RemoteException
Compiling/running the example
-
All the source code is available from
here . This includes an ant
build.xml
file.
-
You can use this to build/run the examples by
ant compile
ant runtickerclock
ant runcomputerclock
-
If you don't want to do it this way, you can run any Java compiler/runtime or IDE with
the classpath set to include the files
${jini_home}/lib/jini-core.jar
${jini_home}/lib/jini-ext.jar
${jini_home}/lib/sun-util.jar
These files are in the Jini 2.0 zip file at
ftp://jan.newmarch.name/pub/jini-1_2_1-src.zip
-
At runtime you also need to specify a security policy file to overcome the "sandbox"
security model. A totally open policy is in the file
policy.all
with contents
grant {
permission java.security.AllPermission "", "";
};
-
The policy file is set by the define
-Djava.security.policy="policy file"
-
You need to compile RMI stubs for the classes that will be sent to remote systems
rmic -v1.2 service.ComputerTimer
rmic -v1.2 service.TickerTimer
-
If you are running in a distributed system, you also need to make the Stub classes
available on an HTTP server. (You can omit this if you are running everything
on the same computer)
copy {ComputerTimer|TickerTimer}_Stub.class HTTP_server_root/classes
-
If you are running in a distributed system, you need to specify this HTTP
server by the define
-Djava.rmi.server.codebase=http://${hostname}/classes/
.
-
Compile looks like
javac -classpath=... SourceFile
-
Run looks like
java -classpath=... -Djava.rmi.server.codebase=... -Djava.security.policy=... ClassFile
Why is it so complicated?
Jini uses mobile code to put a proxy on a client and make RPC calls from the proxy through
to the service. This means
-
The server needs to prepare special versions of classes to act as proxies (the
_Stub
classes)
-
The client has to be able to find the definitions of these classes from a
server somewhere - see "Dynamic class loading" in the
Infrastructure lecture
-
The server needs to copy the files to an HTTP server
-
At runtime the location of these files needs to be passed to the client
-
The client will be running "foreign" code, so needs to have a security policy
to manage what the foreign code will do
-
Note that most of this work is done on the service side - the client only needs
to specify a security policy
Do you need HTTP servers?
-
People working on a single machine with all files accessible from their
classpath discover that they don't need any additional HTTP servers
and don't need to copy stub files anywhere
-
This works, and is good for getting things running the first time
-
In general, the service, the client and the lookup service will all be
running on different machines and don't know of each other's existence
till discovery takes place
-
In general, the service won't have reggie's
reggie-dl.jar
in its classpath; the client won't have the service's files in its
classpath, or the reggie-dl.jar
either, etc
-
So in general, things will break if the client, service and lookup
service can't find each others files
-
The HTTP servers are needed if you are running on separate machines,
or if the classpaths of the various things don't include the files
of the other bits
Running a lookup server
Sigh, as if that wasn't enough...
-
Jini requires a lookup service (LUS) in order to function (but a student here is trying
to simplify that...)
-
The LUS needs to run an HTTP server to deliver its proxies. This is
done by
java -jar $JINI_HOME/lib/tools.jar -port 8080 -dir $JINI_HOME/lib
-
The LUS needs to have a security policy to handle remote classes that it uploads.
A suitable policy is in
$JINI_HOME/reggie/start.policy
-
And now, in order to make a very flexible system, Jini uses a level of indirection
by a "starter" system. So you have run the starter, and then tell it what it is
starting :-(((
java $JINI_HOME/lib/start.jar start-transient-reggie.config
The config file says (in a complicated - but flexible - way) "start a LUS"
-
An example of is
import com.sun.jini.start.ServiceDescriptor;
import com.sun.jini.start.NonActivatableServiceDescriptor;
import com.sun.jini.config.ConfigUtil;
com.sun.jini.start {
private static codebase = "http://192.168.1.11:8080/reggie-dl.jar";
private static policy = "/usr/local/reggie/reggie.policy";
private static classpath = "/usr/local/jini2_0/lib/reggie.jar";
private static config = "/usr/local/reggie/transient-reggie.config";
static serviceDescriptors = new ServiceDescriptor[] {
new NonActivatableServiceDescriptor(
codebase, policy, classpath,
"com.sun.jini.reggie.TransientRegistrarImpl",
new String[] { config })
};
}
-
The config file makes reference to another config file,
/usr/local/reggie/transient-reggie.config
. The contents
of this could be
com.sun.jini.reggie {
initialMemberGroups = new String[] {};
}
Jan Newmarch <jan@newmarch.name>
Last modified: Thu May 27 18:44:23 EST 2004