Building Service-Based Architectures With Jini
by Bill Pierce


Listing One
 --  RemoteServer.java   --------------------------  
import java.rmi.*;
public interface RemoteServer extends Remote {
  public ReturnValue takeThisAndGiveMeThat(ParameterValue myThis) 
         throws RemoteException;
  // public ReturnValue anotherMethodInTheInterface(ParameterValue myThis) 
  //        throws RemoteException;
}
 --  ParameterValue.java   --------------------------  

import java.io.Serializable;
public interface ParameterValue 
       extends   Serializable   {
   public int get();
}
 --  ReturnValue.java   --------------------------  
import java.io.Serializable;
public interface ReturnValue 
       extends   Serializable  {
   public int get();
}
 --  ConcreteParameterValue.java   --------------------------  
public class ConcreteParameterValue 
       implements ParameterValue     {
  public int get() {
    return 8;
  }
  //  protected void anUnrelatedMethod() {
  //  }
}
 --  ConcreteReturnValue.java   --------------------------  
public class ConcreteReturnValue 
       implements ReturnValue     {
  // static final long serialVersionUID = 6679126200670664714L;
  // private int unusedPrivateField = 5;
  public int get() {
    return 7;
  }
  protected int someInternallyUsedMethod() {
    return 7;
  }
  // public int anotherInternallyUsedMethod() {
  //   return 12;
  // }
}
 --  RemoteClient.java   --------------------------  
import java.rmi.*;
public class RemoteClient {
 private RemoteServer server = null;
 public RemoteClient() throws Exception {
    System.setSecurityManager(new RMISecurityManager());
    server = lookupServer(); 
 }
 private RemoteServer lookupServer() throws Exception {
    RemoteServer aServer;
    JiniUtilities utils = new JiniUtilities("jini://127.0.0.1");
    aServer = (RemoteServer) utils.findService("RemoteServer");
    return aServer;
 }
 public void exchangeThisAndThatWithServer() {
    ParameterValue myThis;
    ReturnValue    myThat;
    try {
       myThis = new ConcreteParameterValue();
       myThat = server.takeThisAndGiveMeThat(myThis);

       System.out.println("I gave this: " +
                          Integer.toString(myThis.get()) +
                          " I got that: "  +
                          Integer.toString(myThat.get())
                          );
       // System.out.println("Calling another method.");
       // myThat = server.anotherMethodInTheInterface(myThis);
    } catch (Exception e) {
       System.err.println(e.toString());
    }
 }
 public static void main(String[] args) {
   try { 
     RemoteClient client = new RemoteClient();
     client.exchangeThisAndThatWithServer();
   } catch (Exception e) {
     System.err.println("RemoteClientFailed " + e.toString());
   }
 }
} // End of RemoteClient.
 --  RemoteServerImpl.java   --------------------------  
import java.rmi.*;
import java.rmi.server.*;
public class      RemoteServerImpl 
       extends    UnicastRemoteObject 
       implements RemoteServer         {
  private static final int KEEPALIVE_LOOP_INTERVAL = 1000000;
  public RemoteServerImpl() throws Exception {
     System.setSecurityManager(new RMISecurityManager());
     (new JiniUtilities("jini://127.0.0.1/")).registerService(this); 
  }
  public ReturnValue takeThisAndGiveMeThat(ParameterValue myThis) 
         throws RemoteException 
  {
      myThis.get();
      ReturnValue that = new ConcreteReturnValue();
      return that;
  }
  public static void main(String[] args) {
   try {
      RemoteServer myServer = new RemoteServerImpl();
      while (true) {
         Thread.sleep(KEEPALIVE_LOOP_INTERVAL);
      }
   } catch (Exception e) {
      System.err.println("RemoteServer failed " + e.toString());
   }
  }
} // End of RemoteServerImpl.

 --  JiniUtilities.java   --------------------------  
import java.rmi.*;
import net.jini.core.lookup.*;
import net.jini.core.lease.*;
import net.jini.core.discovery.*;

import com.sun.jini.lease.*;

/** An a minimalist utility class to encapsulate registration
 *  and lookup of Jini services against a single lookup service
 *  found by unicast discovery.  This code is for illustration  only.
 */
public class JiniUtilities
       implements LeaseListener  
{
    /* A cached handle to the lookup service.  */
    public ServiceRegistrar registrar;
    /* A utility that will take care of periodically renewing
     * our service's leases with the lookup service.
     */
    public LeaseRenewalManager leaseManager;
    /* JiniUtilities(String) instantiates a JiniUtilities
     *  locating the lookup service via a unicast "discovery." 
     */
    public JiniUtilities(String requestedURL)
        throws Exception
    {
        registrar = unicastDiscover(requestedURL);
        leaseManager = new LeaseRenewalManager();
    }
    /* This discovers the lookup service that we register and retrieve 
     * services from via a unicast discovery method.
     */
    private ServiceRegistrar unicastDiscover(String url)
        throws Exception
    {
        LookupLocator lookup;
        ServiceRegistrar registrar = null;
        try {
            lookup = new LookupLocator (url);
            registrar  = lookup.getRegistrar();
        } catch (Exception e) {
            System.err.println("JiniUtils: Unicast search for " + 
                               url + " failed: " + e.toString());
            throw e; 
        }
        return registrar;
    }
    /* Register the specified service and, in this case,
     * set it up to renew its lease "forever."
     */
    public void registerService(Remote service)
        throws RemoteException
    {
        ServiceID savedServiceID = getServiceID(service);
        ServiceItem item = new ServiceItem(savedServiceID, service, null);
        ServiceRegistration reg = null;
        try {
            reg = registrar.register(item, Lease.FOREVER);
            leaseManager.renewUntil(reg.getLease(), Lease.FOREVER, this);
        } catch(java.rmi.RemoteException e) {
            System.err.println("JiniUtilities: Register exception: " + 
                               e.toString());
            throw e;
        }
    }
    /* Ensures that services always register with the same serviceID. If 
     * multiple services were involved, these serviceIDs would be handed 
     * out by the lookup service and persisted in a file. For this 
     * experiment simply return a constant ServiceID.
     */
    private ServiceID getServiceID(Remote service) {
        return new ServiceID(7L,7L);
    }
    /* Find the first available service implementing specified interface. */
    public Object findService(String classname)
        throws Exception
    {
        Object foundService = null;
        try {
            Class [] classes = new Class[] {Class.forName(classname)};
            ServiceTemplate template = new ServiceTemplate(null   , 
                                                           classes,
                                                           null      );
            foundService = (Object) registrar.lookup(template);
        } catch (java.rmi.RemoteException e) {
            System.err.println(
                   "JiniUtilities: exception when finding service!"
                              );
            throw e;
        }
        return foundService;
    }
    /* This is called when a LeaseRenewelManager fails to renew a
     * service lease.  See LeaseListener for more details.  
     */
    public void notify(LeaseRenewalEvent evt) {
        System.out.println("JiniUtils: Lease expired: " + evt.toString());
    }
} // End of JiniUtilities.


Listing Two
 --  RemoteClient.java   --------------------------  
import java.rmi.*;
import java.util.Date;
public class RemoteClient {
 private RemoteServer server = null;
 public RemoteClient() throws Exception {
    server = lookupServer(); 
 }
 public RemoteServer lookupServer() throws Exception {
    RemoteServer aServer;
    aServer = (RemoteServer) Naming.lookup("RemoteServer");
    return aServer;
 }
 public long timeRemoteCall() {
    Date start, finish;
    long delta;
    start = new Date();
    try {
       server.doIt();
    } catch (RemoteException re) {
       System.err.println("Hit a RemoteException");
    } catch (Exception e) {
       System.err.println("Hit a different Exception");
    } finally {
       finish = new Date();
    }
    delta = finish.getTime() - start.getTime();
    return delta;
 }
 public static void main(String[] args) {
   try { 
    RemoteClient client = new RemoteClient();
    while(true) {
       long elapsedTime = client.timeRemoteCall();
       System.out.println("Remote call time was "   + 
                          Long.toString(elapsedTime)  );
    }
   } catch (Exception e) {
     System.err.println("RemoteClientFailed " + e.toString());
   }
 }
} // End of RemoteClient.

 --  RemoteServer.java   --------------------------  
import java.rmi.*;
public interface RemoteServer extends Remote {
  public void doIt() throws RemoteException;
}

 --  RemoteServerImpl.java   --------------------------  
import java.rmi.*;
import java.rmi.server.*;

public class      RemoteServerImpl 
       extends    UnicastRemoteObject 
       implements RemoteServer         {
  public RemoteServerImpl() throws Exception {
     Naming.rebind("RemoteServer", this);
  }
  public void doIt() throws RemoteException {
      // do nothing.
  }
  public static void main(String[] args) {
   try {
      new RemoteServerImpl();
   } catch (Exception e) {
      System.err.println("RemoteServer failed " + e.toString());
   }
 }
} // End of RemoteServerImpl.





1

