Exercise 2. JINI
What this exercise is about
This exercise extends the previous exercise to provide for handling remote events. This addition supports running the "Hello World" service after the client has started.
What you should learn
Introductions
The program we will write reuses the code of Exercise 1 by subclassing and inheriting all of the functionality of Exercise 1. The new code adds event handlers and overrides methods of Exercise 1 to add these event handlers. The Jini framework just utilizes the Remote Method Invocation (RMI) remote event framework. This framework requires
How it will work
The client will start and create an event listener object that will be able to respond to remote events. The client will, as part of the new overridden lookup routine, solicit an event from the lookup service if it does not find a service at the lookup service. This is done by remotely calling a notify()method of the lookup service that has been registered as a remote method available by the lookup service. This passes responsibility to the lookup service to all your notify() if a service registers that you are interested in.
The notify()method of the lookup service requires 5 parameters:
TRANSITION_MATCH_NOMATCH – notify me when a previously matching service changes and no longer matches
TRANSITION_NOMATCH_MATCH – notify me when a matching value appears
TRANSITION_MATCH_MATCH – notify me when a matching value changes.
The code we implement is from Chapter 5 of the Core Jini book by Keith Edwards.
To avoid the typing, ftp the source code for this java program from shop110ab.cse
You can use account guest with password shop110guest
The code is found in /opt/jini/corejini/chapter5/HelloWorldClientWithEvents.java. We will walk through this code. You may safely jump to step 10 if you don’t want to deal with the details of the code or get lost in these details.
The Client code
// Extend the client so that it can receive events
// when new services appear.
package corejini.chapter5;
import net.jini.core.lookup.ServiceEvent;
import net.jini.core.lookup.ServiceItem;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.event.RemoteEvent;
import net.jini.core.event.RemoteEventListener;
import net.jini.core.event.UnknownEventException;
import java.util.Vector;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class HelloWorldClientWithEvents extends HelloWorldClient {
protected final int LEASE_TIME = 10 * 60 * 1000;
// 10 minutes
// An inner class to listen for events.
class MyEventListener
extends UnicastRemoteObject
implements RemoteEventListener {
//Null Listener Constructor
public MyEventListener()throws RemoteException {}
_____ 2. The action to take when the lookup service sends us the event indicating a change in the service
// Called when an event is received.
public void notify(RemoteEvent ev)
throws RemoteException, UnknownEventException {
System.out.println("Got an event from: "
+ ev.getSource());
if (ev instanceof ServiceEvent) {
ServiceEvent sev = (ServiceEvent) ev;
ServiceItem item = sev.getServiceItem();
HelloWorldServiceInterface hws =
(HelloWorldServiceInterface) item.service;
System.out.println("Got a matching service.");
System.out.println("It's message is: " +
hws.getMessage());
} else {
System.out.println("Not a service event, " +
"ignoring");
}
}
}
_____ 3. A reference to my listener object;
protected MyEventListener eventCatcher;
_____ 4. Client constructor;
// Same as superclass, only create an event
// listener
public HelloWorldClientWithEvents()
throws RemoteException, IOException {
eventCatcher = new MyEventListener();
}
_____ 5. Client overrides this method of the ancestor
protected Object lookForService(ServiceRegistrar lu) {
_____ 6. Parent does what it did before but now gives the object to the child;
Object o = super.lookForService(lu);
if (o != null) {return o;}
else {
_____7. No service was found
try {
registerForEvents(lu);
}
catch (RemoteException ex) {
System.err.println("Can't solicit events: "
+ ex.getMessage());
// Discard it, so we can find it again
disco.discard(lu);
}
finally {
return null;
}
}
}
_____7. Register with the lookup service for events
// Ask for events from the lookup service
protected void registerForEvents(ServiceRegistrar lu)
throws RemoteException {
lu.notify(
template,
ServiceRegistrar.TRANSITION_NOMATCH_MATCH,
eventCatcher,
null,
LEASE_TIME);
}
_____8. Main just creates an instance of the derived class, but is as before
// Start the client.
public static void main(String args[]) {
try {
HelloWorldClientWithEvents hwc =
new HelloWorldClientWithEvents();
new Thread(hwc).start();
} catch (IOException ex) {
System.out.println("Couldn't create client: "
+ ex.getMessage());
}
}
______ 9. End of client
Compiling and running the new Client
_____ 10. Compile the source code files for the client as before. Work in the files directory and give the command, removing returns, modifying paths and slash directions as required
javac
-classpath c:\jini\jini1_0\lib\jini-core.jar;
c:\jini\jini1_0\lib\jini-ext.jar;
c:\jini\jini1_0\lib\sun-util.jar;
c:\jini\client
-d c:\jini\client
c:\jini\corejini\chapter5\HelloWorldClientWithEvents.java
____ 11. Check your directories and files.
_____ 12. We will need to create a directory for client stubs that will be downloaded to the lookup service.
mkdir client-dl
_____ 12. Create the RMI stubs. This will allow the lookup service to call the notify()method of our client. Here we need to be aware of a bug in some versions of rmic, the program that creates the stups. In some versions the –classpath option overrides the system classpath, and the java virtual machine cannot find core Java classes. In this example the command has included rt.jar in the classpath argument. Try leaving it off the first time to see if the bug is fixed in your version of rmic.
rmic –classpath $JAVA_HOME/jre/lib/rt.jar:
$JINI_HOME/jini1_0/lib/jini-core.jar:
$JINI_HOME/jini1_0/lib/jini-ext.jar;
$JINI_HOME/jini1_0/lib/sun-util.jar;
$HOME/client
-d $HOME/client-dl
corejini.chapter5.HelloWorldClientWithEvents.MyEventListener
____ 12. The client-dl directory should have a corejini.chapter5 subdirectory containing the stub file
HelloWorldCLientWitnEvents$MyEventListener_Stub.class
_____ 13. Start an HTTP server to export the clients downloadable code
java –jar $JINI_HOME/lib/tools.jar
-dir HOME/client-dl –verbose –port 8080
.
_____ 14. Check for the security policy file. If none, Edit a file named policy and place it in your directory.
grant {
// This one allows everyone everything
permission java.security.AllPermission;
} ;
_____ 15. Run the client (a Windows run…modify for unix…i..e slashes and colons)
java -cp
c:\jini\jini1_0\jini-core.jar;
c:\jini\jini1_0\lib\jini-ext.jar;
c:\jini\jini1_0\sun-util.jar;
c:\jini\client
-Djava.rmi.server.codebase=http://myhost:8080
-Djava.security.policy=c:\jini\policy
corejini.chapter5.HelloWorldClientWithEvents
_____ 58. Find someone to register a service