Exercise 1. JINI
What this exercise is about
This exercise is about Jini clients and services. It is a minimal Jini program that uses instances of Discovery to find a Lookup service. That service provides information about a client service. The client fetches and uses the service.
What you should learn
Framework requirements:
In the shop110 lab, all machines are in the 131.204.139.0 TCP/IP subnet. Machines are asssigned their IP addresses or get them by configuring themselves as dhcp clients and obtaining an IP address in the range 200-249 at startup from the lab’s dhcp server (131.204.139.51 shop110ab.cse) . In order to have a name/IP association, the lab uses the College of Engineering’s Domain Name server.
In the shop 110 lab, the dhcp server shop110ab.cse is also a Jini Lookup server. There can be many lookup servers in a subnet. As we will see, a service will register with as many Lookup servers as it finds by its broadcast.
To support Jini lookup, the shop110ab.cse machine also runs the programs "rmid" and an HTTP server.
Steps I took to get a lookup service started were (in this order and used the shop line)
(Windows)
java -jar c:\jini\jini1_0\lib\tools.jar -port 8080 -dir c:\jini\jini1_0\lib –verbose
(shop110ab Linux)
java –jar /opt/jini/ jini1_0/lib/tools.jar -port 8080 -dir c:/opt/jini/jini1_0/lib –verbose
(Windows and shop110ab)
rmid
(Windows on the machine foo.cse.eng.auburn.edu [with a directory c:\temp] )
java -Djava.security.policy=c:\jini\jini1_0\example\lookup\policy
-jar c:\jini\jini1_0\lib\reggie.jar
http://foo.cse.eng.auburn.edu/reggie-dl.jar
c:\jini\jini1_0\example\lookup\policy
c:\temp\reggie_log public
(Linux on shop 110ab.cse [with a directory /tmp])
java -Djava.security.policy=/jini/jini1_0/example/lookup/policy
-jar /jini/jini1_0/lib/reggie.jar
http://shop110.cse.eng.auburn.edu/reggie-dl.jar
/jini/jini1_0/example/lookup/policy
/tmp/reggie_log public
_____ 0. If you want to be a client and not implement a service, jump to step 31.
The service we will implement is from Chapter 5 of the Core Jini book by Keith Edwards. It has an interface as follows
package corejini.chapter5;
public interface HelloWorldServiceInterface {
public String getMessage();
}
The interface defines one simple method. When a client asks for a message, a string is returned. When you write the service you will implement this interface.
We will also be writing a program that finds the lookup service to publish our service and make sure that the lookup service we find holds the lookup for us with a 10 minute lease.
_____ 1. Create workspaces for the sources
Create a directory to work in (e.g. files). Create a subdirectory of this directory named corejini and a subdirectory of corejini named chapter5.
_____ 2. Create directories for executables
Create directories named service and service-dl.
In the service-dl directory create a subdirectory of this directory named corejini and a subdirectory of corejini named chapter5
_____ 3. Remember from now on out that the direction of the slash in paths is operating system dependent.

_____ 4. Create the interface code HelloWorldServiceInterface.java
In the files/corejini/chapter5 directory, enter and save the java interface code
package corejini.chapter5;
public interface HelloWorldServiceInterface {
public String getMessage();
}
_____ 5. Now working from the files directory compile and save the interface code in the service directory with the command.
javac –d service
corejini/chapter5/HelloWorldServiceInterface.java
Some new directories reflecting the packaging have been created by this command.
_____ 6. Make the interface available to the client by download.
Copy the HelloWorldServiceInterface.class file in the service directory to the service-dl/corejini/chapter5 directory to make the interface available to the client by download.
_____ 7. Check your directories and files

_____ 7. Now we will create the service source HelloWorldService.java and put it in the corejini/chapter5 directory (slash direction reminder)
To avoid a lot of 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/HelloWorldService.java. We will walk through this code, and make some changes in step 10. You may safely jump to step 25 if you want to invest in the details of the service later or get lost in the details of what is going on.
The Service code
// This is the first iteration of a Hello, World service
// --it publishes a proxy that returns
// a string when asked by clients.
_____ 8. The package statement reflects the directory structure
package corejini.chapter5;
_____ 9. The imports make visible the required Jini classes for discovery and lookup
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.DiscoveryEvent;
import net.jini.discovery.LookupDiscovery;
import net.jini.core.lookup.ServiceItem;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceRegistration;
import java.util.Hashtable;
import java.io.IOException;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
_____ 10. Implement the interface. Change the return string to the message you would like to return
// This is the proxy object that will be downloaded
// by clients. It's serializable and implements
// theHelloWorldServiceInterface.
class HelloWorldServiceProxy implements
Serializable,
HelloWorldServiceInterface
{
public HelloWorldServiceProxy() {
}
public String getMessage() {
return "Hello, world!";
}
}
_____ 11. Notice that the proxy implements serializable. This is required for a service proxy and supports a copy of an instance object converted to a byte stream and moved to a client. The no-argument constructor is required for classes that implement Serializable.
_____ 12. The HelloWorldProxy class is a private class in the file that is used only by objects of the public class HelloWorldService which names the source file. Clients get access to this via the serialization.
// HelloWorldService is the "wrapper" class that
// handles publishing the service item.
public class HelloWorldService implements Runnable {
_____ 13. This class serves to find the lookup service and publish the proxy. It contains the main and declares storage required to manage the proxy.
// 10 minute leases
protected final int LEASE_TIME = 10 * 60 * 1000;
// Need to manage any lookup servers we discover
protected Hashtable registrations = new Hashtable();
// Instances of this class are given to the lookup service
protected ServiceItem item;
// instances are used for the discover protocol
protected LookupDiscovery disco;
_____ 14. Delegation is used as the framework for lookup and discovery. Whenever a lookup service is found we pass this service a Listener instance. This object is called by the lookup service when it wants to initialize or discard our service.
// Inner class to listen for discovery events
class Listener implements DiscoveryListener {
// Called when we find a new lookup service.
public void discovered(DiscoveryEvent ev) {
System.out.println(
"discovered a lookup service!");
ServiceRegistrar[] newregs =
ev.getRegistrars();
for (int i=0 ; i<newregs.length ; i++)
{
if (!registrations.containsKey(newregs[i]))
{
registerWithLookup(newregs[i]);
}
}
}
// Called ONLY when we explicitly discard a
// lookup service, not "automatically" when a
// lookup service goes down. Once discovered,
// there is NO ongoing communication with a
// lookup service.
public void discarded(DiscoveryEvent ev) {
ServiceRegistrar[] deadregs =
ev.getRegistrars();
for (int i=0 ; i<deadregs.length ; i++) {
registrations.remove(deadregs[i]);
}
}
}
____ 15. The constructor for our service provides all initialization.
public HelloWorldService() throws IOException {
_____ 16. Create the proxy item. This is done by a class method only for possible subclassing reasons. The first parameter if null the first time will ask the lookup service to assign a globally unique id. Subsequent re-registrations should use this id. For now we’ll get a new id every time.
The second parameter serializes the object
The third parameter is a hook that allows us to provide a list of attributes along with the service. Tor example, if we were registering a printer we might attach information about its location, model, etc. For now it is null.
item = new ServiceItem(null, createProxy(), null);
_____ 17.
// Set a security manager
if (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
_____ 18. Find a lookup service
// Search for the "public" group, which by
// convention is named by the empty string
disco = new LookupDiscovery(new String[] { "" });
_____ 19. // Install a listener.
disco.addDiscoveryListener(new Listener());
}
_____ 20. Serializes our service
protected HelloWorldServiceInterface createProxy() {
return new HelloWorldServiceProxy();
}
_____21.
// This work involves remote calls, and may take a
// while to complete. Thus, since it's called from
// discovered(), it will prevent us from responding
// in a timely fashion to new discovery events. An
// improvement would be to spin off a separate short-
// lived thread to do the work.
protected synchronized void
registerWithLookup(ServiceRegistrar registrar)
{
ServiceRegistration registration = null;
try
{
registration = registrar.register(item,
LEASE_TIME);
}
catch (RemoteException ex) {
System.out.println("Couldn't register: "
+ ex.getMessage());
return;
}
_____22.
// If this is our first registration, use the
// service ID returned to us. Ideally, we should
// save this ID so that it can be used after
// restarts of the service
if (item.serviceID == null) {
item.serviceID = registration.getServiceID();
System.out.println("Set serviceID to " +
item.serviceID);
}
registrations.put(registrar, registration);
}
_____23. Our service class implements runable. This is so that the application won’t stop when the main exits. Without at least one active non-daemon thread the virtual machine would stop. With GUI based programming this will not be necessary since threads are created to manage windows.
// This thread does nothing but sleep, but it
// makes sure the VM doesn't exit.
public void run() {
while (true) {
try {
Thread.sleep(1000000);
} catch (InterruptedException ex) {
}
}
}
_____ 24. The main program
// Create a new HelloWorldService and start its thread.
public static void main(String args[]) {
try {
HelloWorldService hws =
new HelloWorldService();
new Thread(hws).start();
} catch (IOException ex) {
System.out.println("Couldn't create service: "
+ ex.getMessage());
}}}
_____ 25. Compiling the service. In the following the $JINI_HOME should replaced with the directory that contains the jini1_0 directory, and $HOME with the path to the directory in which you created the service directory. Eliminate the multiple lines, but no spaces after the ‘;’. There is another operating system dependent issue here as well. Linux for example requires a colon (:) separating the directories in the classpath.
Compile the source files and place the classes generated in the services directory. Work from the files directory with this command.
javac –classpath $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/service -d $HOME/service
corejini/chapter5/HelloWorldService.java
____ 26. Copy the compiled HelloWorldServiceProxy.class file
into the service-dl/corejini/chapter5 directory for download by a web server. Check that the class files have been added to the correct subdirectory of service corresponding to the package.
_____ 27. Start an HTTP server for your service
java –jar $JINI_HOME/jini1_0/lib/tools.jar
-dir $HOME/files/service-dl –verbose –port 8080
_____28 Set up a security policy file. Edit a file named policy and place it in your files directory.
grant {
// This one allows everyone everything
permission java.security.AllPermission;
} ;
_____ 29. Now run your service (a Windows run…modify for unix). Use YOUR machine name or IP address instead of "began"
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\service
-Djava.security.policy=c:\jini\policy
-Djava.rmi.server.codebase=
http://began.cse.eng.auburn.edu:8080/
corejini.chapter5.HelloWorldService
_____ 30. Find someone to start a client to find your service, or follow the client steps that follow.
The client we will implement is from Chapter 5 of the Core Jini book by Keith Edwards. It has an interface as follows
package corejini.chapter5;
public interface HelloWorldServiceInterface {
public String getMessage();
}
The interface defines one simple method. When the client asks for a message, a string is returned. When you write the client you will use an implementation of this interface.
We will also be writing a program that finds the lookup service to request the service.
_____ 31. Create workspaces for the sources
Create a directory to work in (e.g. files). Create a subdirectory of this directory named corejini and a subdirectory of corejini named chapter5.
_____ 32. Create directories for executables
Create a subdirectory named client
_____ 33.

_____ 34. Create the interface code HelloWorldServiceInterface.java
In the files/corejini/chapter5 directory, enter and save the java interface code
package corejini.chapter5;
public interface HelloWorldServiceInterface {
public String getMessage();
}
_____ 35. Now working from the files directory compile and save the interface code in the client directory with the command
javac –d ./client
corejini/chapter5/HelloWorldService.java
Some new directories reflecting the packaging have been created by this command.
_____ 36. Check your directories and files

_____ 36. Now we will create the client source HelloWorldClient.java
To avoid a lot of 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/HelloWorldClient.java. We will walk through this code. You may safely jump to step 55 if you want to invest in the details of the client or get lost in these details.
The Client code
// A simple Client to exercise the HelloWorldService
_____ 37. The package statement reflects the directory structure
package corejini.chapter5;
_____ 38. The imports make visible the required Jini classes for discovery and lookup
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.DiscoveryEvent;
import net.jini.discovery.LookupDiscovery;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceTemplate;
import java.util.Vector;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
_____ 39. As with the server, the client class implements the runnable interface so that it can create a thread to keep the program from exiting when the main reaches the end of its code.
public class HelloWorldClient implements Runnable {
_____ 40. The client storage required for lookup and discovery. After discovery of a lookup service, a service template is given the lookup service containing the information we seek.
protected ServiceTemplate template;
_____41. Three fields of this template are worth remembering for this example.
public class ServiceTemplate {
public ServiceID serviceID;
public Class[] serviceType;
public Entry[] attributeSetTemplates; …
_____ 42. The lookup service that we discover.
protected LookupDiscovery disco;
_____ 43. The client program is similar to the server. It has an inner class that implements DiscoveryListener in order to participate in the discovery protocol.
// An inner class to implement DiscoveryListener
class Listener implements DiscoveryListener {
_____ 44. This method is called by a lookup server when found. It gives us access to services. We usa a local method "lookForService() to find the service we want.
public void discovered(DiscoveryEvent ev) {
ServiceRegistrar[] newregs =
ev.getRegistrars();
for (int i=0 ; i<newregs.length ; i++) {
lookForService(newregs[i]);
}
}
public void discarded(DiscoveryEvent ev) {
}
}
_____ 45. This is the constructor for the client
public HelloWorldClient() throws IOException {
_____ 46. This is the service we are interested in, and we register it in the template.
Class[] types =
{ HelloWorldServiceInterface.class };
template = new ServiceTemplate(null, types, null);
_____ 47. . This method also installs a security manager needed to download and use the service.
// Set a security manager
if (System.getSecurityManager() == null) {
System.setSecurityManager(
new RMISecurityManager());
}
_____ 48. Find a lookup service. The null string indicates the public group
// Only search the public group
disco = new LookupDiscovery(new String[] { "" });
_____ 49. This is where our inner class is given to the discovery object
// Install a listener
disco.addDiscoveryListener(new Listener());
}
_____ 50.
// Once we've found a new lookup service, search
// for proxies that implement
// HelloWorldServiceInterface
protected Object lookForService(ServiceRegistrar lusvc) {
Object o = null;
try {
o = lusvc.lookup(template);
} catch (RemoteException ex) {
System.err.println("Error doing lookup: "
+ ex.getMessage());
return null;
}
if (o == null) {
System.err.println("No matching service.");
return null;
}
System.out.println("Got a matching service.");
System.out.println("It's message is: " +
((HelloWorldServiceInterface)o).getMessage());
return o;
}
_____ 51. This is the background thread so that the main will not exit before a service is found.
// This thread does nothing--it simply keeps the
// VM from exiting while we do discovery.
public void run() {
while (true) {
try {Thread.sleep(1000000);}
catch (InterruptedException ex) {}
}
}
_____ 52. The main program.
// Create a HelloWorldClient and start its thread
public static void main(String args[]) {
try {
HelloWorldClient hwc = new HelloWorldClient();
new Thread(hwc).start();
}
catch (IOException ex)
{
System.out.println("Couldn't create client: " +
ex.getMessage());
}
}
}
_____ 53. The service Template was the key to finding a match to a class or interface, attributes or a specific service ID. The type system is used in matching. Services that are subtypes of known types can be found. If by inheritance, a class B extends a class A then a search for class A will return all objets of type A or of type B registered by the lookup service.
_____54. The call to lookup also returns a proxy object for itself. Setting the template field to null matches all services found in the lookup service. In our case we only set the type HelloWorldServiceInterface.
Compiling and running the Client
_____ 55. Compile the source code files for the client. 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\HelloWorldClient.java
_____ 56. Check your directories and files.
_____ 57. Set up a security policy file. Edit a file named policy and place it in your files directory.
grant {
// This one allows everyone everything
permission java.security.AllPermission;
} ;
_____ 58. Find someone to register a service
_____ 59. Now run your 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.security.policy=c:\jini\policy
corejini.chapter5.HelloWorldClient