Exercise 3. JINI

 

What this exercise is about

 

This exercise extends previous exercises to provide for management of leases.

 

What you should learn

 

  1. Understanding how the Jini framework can manage leases.

 

 

Introductions

 

 

The program we will write reuses the Client code of Exercise 1 and the Server code of Exercise 2 by subclassing and inheriting functionality. Sun provides a leasing package, but it is not used in this exercise.

 

 

How it will work

 

The Server will start and the thread of Exercise 1 that kept the service going will be used to handle the lease management. The new implementation of run()will sleep until it is awaken to renew a lease, then go back to sleep.

 

The interesting thing about this example is that we need to remember that the discovered()method of the client is in another thread, and that a new lookup service registration may happen at any time. If a new lease is added while the thread is asleep, that lease may be shorter than the next scheduled wakeup. So the registerWithLookup()method is also overridden to call the super method and then wake up the lease management thread.

 

 

To avoid 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/HelloWorldServiceWithLeases.java. We will walk through this code. You may safely jump to step 8 if you want to invest in the details of the service later or get lost in the details of what is going on.

 

 

 

 

 

 

The new Server

 

 

// Extend HelloWorldService to renew its service

// registration leases.

 

package corejini.chapter5;

 

import net.jini.core.lookup.ServiceRegistrar;

import net.jini.core.lookup.ServiceRegistration;

import net.jini.core.lease.Lease;

import net.jini.core.lease.UnknownLeaseException;

import java.util.Vector;

import java.util.Enumeration;

import java.io.IOException;

import java.rmi.RemoteException;

 

public class HelloWorldServiceWithLeases extends HelloWorldService {

protected Thread leaseThread = null;

 

public HelloWorldServiceWithLeases() throws IOException { }

 

_____ 1. This overriding method calls the ancestor and then wakes up the lease thread

// Not only register, but also cause the lease

// thread to wake up.

protected void registerWithLookup(ServiceRegistrar lusvc) {

super.registerWithLookup(lusvc);

leaseThread.interrupt();

}

_____ 2. This overriding method run is awaken with an exception or timeout to renew leases

// run now maintains our leases

public void run() {

while (true) {

try {

long sleepTime = computeSleepTime();

Thread.sleep(sleepTime);

renewLeases();

} catch (InterruptedException ex) {

}

}

}

 

_____ 3. Walk through the list of registrations, taking a 20 second fudge time away from the expiration time, and finding the smallest of these values.

 

 

// Figure out how long to sleep.

protected synchronized long computeSleepTime() {

long soonestExpiration = Long.MAX_VALUE;

Enumeration enum = registrations.elements();

while (enum.hasMoreElements()) {

Lease l =

((ServiceRegistration) enum.nextElement()).getLease();

if (l.getExpiration() - (20 * 1000) < soonestExpiration) {

soonestExpiration = l.getExpiration() - (20 * 1000);

}

}

 

long now = System.currentTimeMillis();

if (now >= soonestExpiration) {

return 0;

} else {

return soonestExpiration - now;

}

}

_____ 4. Leases are renewed here and those that cannot be renewed are remembered.

 

// Do the work of lease renewal.

 

protected synchronized void renewLeases() {

long now = System.currentTimeMillis();

Vector deadLeases = new Vector();

Enumeration keys = registrations.keys();

while (keys.hasMoreElements()) {

ServiceRegistrar lu =

(ServiceRegistrar) keys.nextElement();

ServiceRegistration r =

(ServiceRegistration) registrations.get(lu);

Lease l = r.getLease();

if (now <= l.getExpiration() &&

now >= l.getExpiration() - (20 * 1000)) {

try {

System.out.println("Renewing lease.");

l.renew(LEASE_TIME);

} catch (Exception ex) {

System.err.println("Couldn't renew lease: " +

ex.getMessage());

deadLeases.addElement(lu);

}

}

}

_____ 5. Remove those that could not be renewed.

// clean up after any leases that died

for (int i=0, size=deadLeases.size() ; i<size ; i++) {

registrations.remove(deadLeases.elementAt(i));

}

}

 

_____ 6. main starts our new service.

 

// Create the service and start the leasing thread.

 

public static void main(String args[]) {

try {

HelloWorldServiceWithLeases hws =

new HelloWorldServiceWithLeases();

hws.leaseThread = new Thread(hws);

hws.leaseThread.start();

}

catch (IOException ex) {

System.out.println("Couldn't create service: " +

ex.getMessage());

}

}

}

Compiling and running the new Service

 

_____ 8. Compile the source code files for the service 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\service

-d c:\jini\service

c:\jini\corejini\chapter5\HelloWorldServiceWithLeases.java

 

 

____ 9. Check your directories and files. Check that the class files have been added to the correct subdirectory of service corresponding to the package.

 

 

 

_____ 10. Start an HTTP server to export the servers downloadable code

 

 

java –jar $JINI_HOME/lib/tools.jar

-dir HOME/service-dl –verbose –port 8080

.

 

 

 

 

 

 

_____ 11. 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;

} ;

 

 

_____ 12. Run the server (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.HelloWorldServerWithLeases

 

 

The new Client

 

The client (of exercise 2) also needs to manage the leases that it has with the lookup service for an interrupt when a service becomes available. The implementation details are a bit different, but the ideas are the same as the service

 

How it will work

 

The Client will start and the thread of Exercise 2 that kept the client going will be used to handle the lease management. The new implementation of run()will sleep until it is awaken to renew a lease, then go back to sleep. The main implementation difference is a different data structure to store the registrations because different types of registrations are being used: ServiceRegistrations for the Service and EventRegistrations for the client.

 

 

To avoid 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/HelloWorldClientWithLeases.java. We will walk through this code. You may safely jump to step 18 if you want to invest in the details of the service later or get lost in the details of what is going on.

 

 

 

// Extend the client to renew its event registration leases.

 

package corejini.chapter5;

 

import net.jini.core.lookup.ServiceRegistrar;

import net.jini.core.event.RemoteEvent;

import net.jini.core.event.RemoteEventListener;

import net.jini.core.event.EventRegistration;

import net.jini.core.lease.Lease;

import net.jini.core.lease.UnknownLeaseException;

import java.util.Vector;

import java.io.IOException;

import java.rmi.RemoteException;

 

public class HelloWorldClientWithLeases

extends HelloWorldClientWithEvents {

protected Vector eventRegs = new Vector();

protected Thread leaseThread = null;

public HelloWorldClientWithLeases()

throws RemoteException, IOException {}

 

_____ 13. Overridden method adds lease management

 

// When we register for events, add the event's

// registration to the set of managed registrations.

 

protected void registerForEvents(ServiceRegistrar lu)

throws RemoteException {

EventRegistration evreg;

evreg = lu.notify(template,

ServiceRegistrar.TRANSITION_NOMATCH_MATCH,

eventCatcher, null, LEASE_TIME);

eventRegs.addElement(evreg);

leaseThread.interrupt();

}

_____ 14. Overridden method run does the lease management

// run maintains our leases

public void run() {

while (true) {

try {

long sleepTime = computeSleepTime();

Thread.sleep(sleepTime);

renewLeases();

} catch (InterruptedException ex) {

}

}

}

 

// Figure out how long to sleep.

protected synchronized long computeSleepTime() {

long soonestExpiration = Long.MAX_VALUE;

for (int i=0, size=eventRegs.size() ; i<size ; i++) {

Lease l =

((EventRegistration) eventRegs.elementAt(i)).getLease();

if (l.getExpiration() - (20 * 1000) < soonestExpiration) {

soonestExpiration = l.getExpiration() - (20 * 1000);

}

}

long now = System.currentTimeMillis();

if (now >= soonestExpiration) {

return 0;

} else {

return soonestExpiration - now;

}

}

 

_____ 15. Renew and collect unrenewable leases

 

// Do the lease renewal work.

 

protected synchronized void renewLeases() {

long now = System.currentTimeMillis();

Vector deadLeases = new Vector();

for (int i=0 , size=eventRegs.size() ; i<size ; i++) {

Lease l =

((EventRegistration) eventRegs.elementAt(i)).getLease();

if (now <= l.getExpiration() &&

now >= l.getExpiration() - (20 * 1000)) {

try {

System.out.println("Renewing lease.");

l.renew(LEASE_TIME);

} catch (Exception ex) {

System.err.println("Couldn't renew lease: " +

ex.getMessage());

deadLeases.addElement(eventRegs.elementAt(i));

}

}

}

_____ 16. Remove unrenewable leases

 

// clean up after any leases that died

for (int i=0, size=deadLeases.size() ; i<size ; i++) {

eventRegs.removeElement(deadLeases.elementAt(i));

}

}

_____ 17. Main just creates the derived object

 

// Start the service.

public static void main(String args[]) {

try {

HelloWorldClientWithLeases hwc =

new HelloWorldClientWithLeases();

hwc.leaseThread = new Thread(hwc);

hwc.leaseThread.start();

} catch (IOException ex) {

System.out.println("Couldn't create client: " +

ex.getMessage());

}

}

}

 

 

_ Compiling and running the new Client

 

_____ 18. 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\service

-d c:\jini\client

c:\jini\corejini\chapter5\HelloWorldClientWithLeases.java

 

 

____ 19. Check your directories and files. Check that the class files have been added to the correct subdirectory of client corresponding to the package.

 

 

 

_____ 20. Start an HTTP server to export the client’s downloadable code

 

 

java –jar $JINI_HOME/lib/tools.jar

-dir HOME/client-dl –verbose –port 8080

.

 

_____ 21. 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;

} ;

 

 

 

 

 

_____ 22. 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.HelloWorldClientWithLeases