Gopalan Suresh Raj's Web Cornucopia
An Oasis for the parched Enterprise Services Engineer/Developer

    Distributed Computing-Jini Technology

    Distributed-Computing

    Jini is probably one of the most exciting Java technologies introduced by Sun during 1998. Inspired by the genius of Sun’s chief scientist, Bill Joy, Jini is astounding in its scope and potential implications. Fundamentally, Jini is a distributed-object computing technology and is all about ubiquitous network-centric computing. Jini also relies heavily upon Java 2 RMI because all low-level communication is handled using that protocol.

    In the world of Jini computing, just about everything is a distributed object. The distributed services available are not restricted to conventional database and transactional services. They may also include the capabilities of network enabled hardware devices like printers, fax machines, telephones, digital cameras, disk drives, TV’s, and so forth.

    But how does a TV or a disk drive become a distributed object? That small detail is handled by the Jini architecture. Jini objects—be they software or hardware entities—need to implement the core Jini technology. Being an amazingly compact Java binary of around 48K, this core can easily be incorporated within any Java software by implementing the Jini class library or it can be embedded at the device level within almost any hardware containing a JVM.

    Jini obviously seems to derive much of its inspiration from that ubiquitous appliance—the common telephone—and hopes to make using any Jini-enabled device just as simple. In fact, the only external interfaces for Jini-enabled devices are a power cord and a telephone plug! Consequently, Jini-enabled devices are network-enabled by literally plugging them into one, much like you would a conventional telephone. Sun even has a new phrase for this spontaneous networking: “Plug and Work!”

    How Jini works

    Jini is all about providing users ubiquitous access to resources—be they hardware devices or software objects—within a dynamic, distributed Jini system or djinn. Each resource can, in turn, offer multiple services; for instance, a fax machine can offer a faxing service, a hard disk can offer a storage service, a compression object can offer data compression service, and so forth. Jini also terms this networked agglomeration of software and hardware entities as a federation. Figure 1 shows a typical Jini system consisting of numerous software and hardware services.

    Figure 1: A distributed Jini system Figure 1: A distributed Jini system

    The main goals of Jini are

    • To enable users to share services and resources over a network.
    • To provide users the ability to access resources anywhere easily on the network, even though the network location of the user may constantly change.
    • To simplify the task of creating and managing network devices, software services, and users.

    The three major components that make up a running Jini system (shown in Figure 2) are

    1. The Jini Client—Anything that would like to make use of the Jini service
    2. The Service Locator—Anything that acts as a Locator/Trader/Broker between the service and the client, and is used to find services in a distributed Jini system.
    3. The Jini Service—Any entity that can be used by a client program or another service (for example, a printer, a VCR, or a software entity like an EJB service)

    Figure 2: The basic architecture of a Jini system Figure 2: The basic architecture of a Jini system

    Although the Jini spec is independent of the protocol used for network communication, the current implementation is based on TCP/IP. Java’s socket support is used to send and receive object code that will be moved around among the three components. Typically, objects in one Java Virtual Machine (JVM) invoke objects on other JVMs using any protocol that supports Java Remote Method Invocation (Java/RMI) like semantics. The object code is serialized and marshaled over the wire.

    The Jini specification also defines

    • A Programming Model that helps you build a distributed system organized as a federation of Jini services and clients.
    • A Runtime Infrastructure that resides on the network and provides mechanisms for adding, removing, locating, and accessing services. The runtime Infrastructure is used by Jini Services to make themselves available when they join the network. It is also used by clients to locate and contact Jini services. The runtime infrastructure consists of support for discovery, join, and lookup.

    The Runtime Infrastructure resides in the Lookup services and in Jini-enabled devices. Lookup services are the central organizing mechanism for Jini-based systems. When a device is plugged into a network, it registers its services with a Lookup service. The device and its services are now part of a federation. When a client wants to locate a Jini service to assist with some task, it consults a Jini Lookup service.

    Lookup services organize the Jini services they contain into groups. A group is a set of registered services identified by a string. "Corporate EJB Servers" group can be services offered by all EJB Servers running in a Company’s local area network. Similarly "EOI Dept Printers" group can be services offered by all Printers on the EOI Dept. local network. A service can be a member of multiple groups. Multiple Lookup services can also maintain the same group. Redundancy can make a Jini system more fault-tolerant.

    The runtime services

    The Runtime Infrastructure enables Jini services to register with Lookup services through a process called discovery and join. Discovery is the process by which a Jini-enabled device locates Lookup services on the network and obtains references to them. Join is the process by which a device registers the services it offers with Lookup services. The runtime infrastructure enables clients to locate and contact services through a process called lookup.

    Discovery

    Discovery is used by both the Jini services and Lookup Locator services to announce their presence on a distributed Jini network. Jini services use this to obtain Lookup service proxies, while Lookup services use this to announce their presence on the network. The discovery process uses three types of subprotocols, depending on the state a Jini component is in. They are

    1. Multicast Request Protocol—used by a new Jini service to call anonymous Lookup services on a LAN using multicast UDP
    2. Multicast Announcement Protocol—used by Lookup services to announce their presence on a LAN using multicast UDP
    3. Unicast Request Protocol—used by Jini services contacting far Lookup services using Unicast TCP

    These subprotocols use four types of packets:

    1. Multicast Request Packet
    2. Multicast Announcement Packet
    3. Unicast Request Packet
    4. Unicast Response Packet—used by both request protocols

    Unicast Discovery Protocol

    Unicast discovery can be used for Lookup services that reside outside the LAN and the address on which they run are already known. Unicast discovery is done using the LookupLocator class located in the net.jini.core.discovery package.

    The LookupLocator class has two f methods getHost() and getPort(), which are useful in multicast situations to retrieve the hostname the Locator is sitting on and its port number. Unicast discovery involves two steps: the discovering entity sends out a Unicast request and then the Lookup service responds with a Lookup service registrar object.

    The following example code in Listing 1, shows how Unicast discovery is done using the LookupLocator class.

    LookupLocator lookup = new LookupLocator("jini://execpc.com/~gopalan");
    LookupLocator lookup2 = new LookupLocator("jini://localhost/", 80);
    ServiceRegistrar registrar = lookup.getRegistrar();
    

    Listing 1: Unicast discovery using the LookupLocator class

    Multicast Announcement Protocol

    The Multicast Announcement protocol is used by Lookup services to announce their presence on the network. This is used whenever a Lookup service is started or a new one becomes available after a network failure. The message the Lookup service sends out with an announcement contains the service ID of this Lookup service, the IP address, the port number where the Unicast discovery of this Lookup service is located, and the list of groups it manages.

    Multicast Request protocol

    If the location of a Lookup service is unknown, a broadcast search must be made for one. Multicast Request protocol is to discover Lookup services that belong to one or more groups. The class LookupDiscovery in the package net.jini.discovery is used for broadcast searches. The listener should implement the DiscoveryListener interface. A typical source module used for Multicast Request is shown in the following Listing 2.

    public void setup (boolean check) {
      String[] groups = {new String (""), new String ("public")}; 
      try { 
       discoverLookup = new LookupDiscovery (groups); 
       discoverLookup.addDiscoveryListener(this); 
      } catch(IOException e) { 
       // a socket problem during startup 
       e.printStackTrace ();
      } 
     }
    
     public void run () { 
      int priority = Thread.currentThread ().getPriority ();
      Thread.currentThread ().setPriority(Thread.MIN_PRIORITY); 
      while (!discovered); // busy waiting
      Thread.currentThread ().setPriority (priority); 
     }
    
     public void discovered (DiscoveryEvent e) {
      System.out.println("EchoServer: discovered...");
      ServiceRegistrar[] registrar = e.getRegistrars (); 
      lookupRegistrar = (ServiceRegistrar) registrar [0];
      discovered = true;
     } 
    
     public void discarded (DiscoveryEvent e) {
      // so be it 
      System.out.println("EchoServer: discarded...");
     }
    

    Listing 2: A typical source module used for Multicast Request

    The discovering Jini service drops a multicast UDP presence announcement onto a well-known port. Each announcement contains a list of names of groups the Jini service is interested in joining, the IP address and port number where the service can be contacted by Lookup services, and the list of Lookup services it has heard from already. Lookup services monitor the well-known port for presence of any announcement packets. As soon as a Lookup service receives a presence announcement, it inspects the list of group names contained in the packet. If the Lookup service maintains any of these groups, it contacts the sender of the packet directly. The Discovering Jini service, uses the Unicast discovery protocol to obtain a “Lookup Service Registrar.”

    Join

    Discovery provides the Lookup service proxies to the Jini service. The join process is used to register the Jini service proxy at the Lookup service through the Lookup service proxy obtained in discovery. Once registered, the Lookup service contains an entry corresponding to its serviceID and its attributes. The code snippet in Listing 3 shows the Join Process.

    /*
    Create the attributes (an array of entry objects) that describe
    this server and use it to register this server with the lookup
    service. JoinManager finds and registers with the lookup
    service.
    =============================================================== */
    Entry [] aeAttributes;
    JoinManager joinmanager;
    EchoServer myServer;
    aeAttributes = new Entry []{
    new ServiceInfo(PRODUCT,
    MANUFACTURER,
    VENDOR,
    VERSION,
    null, null),
    new BasicServiceType("EchoServer")
    };
    myServer = new EchoServer ();
    joinmanager = new JoinManager (myServer, aeAttributes, myServer,
    new LeaseRenewalManager ());
    

    Listing 3: The Join process

    Once a Jini service discovers a Lookup service, it can register its own services on that Lookup service using the join process. The Jini service connects to the Lookup service through the service registrar object it received from the Lookup service in the discovery process. Through the service registrar object, the Jini service sends information about itself to the Lookup service. The Lookup service stores the uploaded information from the Jini service and associates that service with its requested group. The Jini service has now joined the group on the Lookup service. Figure 3 highlights the Jini runtime characteristics.

    Figure 3: Runtime characteristics—discovery, join, and lookup Figure 3: Runtime characteristics—discovery, join, and lookup

    Lookup

    A distributed Jini client looking up for a Jini service obtains a Jini service proxy from the Lookup service proxy it has. The client selects a template mask for its service and requests it from the Lookup service proxy. Only service proxies that match the mask template are returned. A typical piece of client code is shown in the following Listing 4.

    /*
    * Perform a search on the lookup server to find the service
    * that has the name attribute of "EchoServer". The lookup
    * service returns an interface object to the service.
    * ========================================================= */
    aeAttributes = new Entry[1];
    aeAttributes[0] = new Name ("EchoServer");
    template = new ServiceTemplate (null, null, aeAttributes);
    myServerInterface = (EchoInterface) registrar.lookup (template);
    

    Listing 4: A typical source module used for Lookup

    The template mask filled in by the client consists of the serviceID, service interfaces, and Entry sets. A wildcard value of null acts as a “do not care.” The wildcard can be applied to any template field. The requested objects should match the interface exactly.

    The echo service

    Now we develop a Jini echo service. The client sends a message to the service and the server responds with the same message. The client finds the difference in timestamps between the time it sent out the message and the time it took to receive it, and computes network latency.

    The remote interface

    Because remote interface is a Jini echo service, it simply echoes its input to its output. The interface is shown in the following. Note, the interface is explicitly marked public to prevent the IllegalAccessError on the client. Listing 5 below, shows the EchoInterface definition.

    public interface EchoInterface extends java.rmi.Remote { 
     String echoMessage (String message) 
      throws java.rmi.RemoteException;
    }
    

    Listing 5: The EchoInterface interface definition

    The Jini echo service

    Notice we implement the echoMessage() method here, which sends its input back out. In our main() method, we first set the security manager. The service then creates the attributes (an array of entry objects) that describe this server and uses it to register this server with the Lookup service. The JoinManager finds and registers with the Lookup service. We find the Jini Lookup service (reggie) and print its location. We also get the Lookup service’s ServiceRegistrar (the class by which interaction with the Lookup service is possible). We then itemize the service items and the service objects available in the Lookup service. Listing 6 below, shows the Jini Service class.

    import net.jini.core.entry.*;
    import net.jini.core.lookup.*;
    import net.jini.core.discovery.*; 
    import net.jini.lookup.entry.*;
    import net.jini.discovery.*;
    import com.sun.jini.lookup.*;
    import com.sun.jini.lease.*;
    import java.io.*;
    import java.rmi.*;
    import java.rmi.server.*;
    
    // EchoServer -- The Jini Server Class
    public class EchoServer extends UnicastRemoteObject 
     implements EchoInterface, ServiceIDListener, Serializable {
     
     public EchoServer() throws RemoteException { 
      super (); 
     }
    
     // EchoInterface
     public String echoMessage (String message) throws RemoteException { 
      System.out.println ("EchoServer: The method echoMessage()"+
                          "in EchoServer was called");
      System.out.println ("EchoServer: Client says :" + message);
      return (message);
     }
    
     // ServiceIDListener
     public void serviceIDNotify (ServiceID idIn) { 
     } 
    
     public static void main (String[] args) {
      int iPort;
      String sHost;
      EchoServer myServer;
      LookupLocator lookup;
      Entry [] aeAttributes;
      JoinManager joinmanager;
      ServiceID id; 
      ServiceMatches matches;
      ServiceRegistrar registrar;
      try {
      /* 
       * Setting the security manager to allow the RMI class loader
       * to go to the codebase for classes that are not available
       * locally.
       * ========================================================== */
       System.setSecurityManager (new RMISecurityManager ());
    
      /* 
       * Create the attributes (an array of entry objects) that describe 
       * this server and use it to register this server with the lookup
       * service. JoinManager finds and registers with the lookup 
       * service.
       * =============================================================== */
       aeAttributes = new Entry [1];
       aeAttributes[0] = new Name ("EchoServer");
       myServer = new EchoServer ();
       joinmanager = new JoinManager (myServer,aeAttributes,
                                      myServer,new LeaseRenewalManager());
       System.out.println ("EchoServer: JoinManager = " + joinmanager);
    
      /* 
       * Find the Jini lookup service (reggie) and print its location.
       * ============================================================= */
       lookup = new LookupLocator ("jini://" + args[0]);
       sHost = lookup.getHost ();
       iPort = lookup.getPort ();
       System.out.println ("EchoServer: LookupLocator = " + lookup);
       System.out.println ("EchoServer: LookupLocator.host = " + sHost);
       System.out.println ("EchoServer: LookupLocator.port = " + iPort);
    
      /* 
       * Get the lookup service's ServiceRegistrar (the class by which
       * interaction with the lookup service is possible).
       * ============================================================= */
       registrar = lookup.getRegistrar();
       id = registrar.getServiceID ();
       System.out.println ("EchoServer: ServiceRegistrar = " + registrar);
       System.out.println ("EchoServer: ServiceID = " + id);
    
      /* 
       * Itemize the service items and the service objects that are 
       * available in the lookup service. Note: Sometimes this is 
       * executed too quickly for the service that was registered above 
       * to show up. 
       * ============================================================== */
       try {Thread.sleep (2000);} catch (Exception e) {}
       matches = registrar.lookup(new ServiceTemplate (null, null, 
                                                       null),50);
       System.out.println ("EchoServer: ServiceMatches = " + matches);
       System.out.println ("EchoServer: num matches = "+ 
                           matches.totalMatches);
       for (int i = 0; i < matches.totalMatches; i++) {
        System.out.println ("EchoServer: svc item " + i + ": " + 
                            matches.items[i]);
        System.out.println ("EchoServer: svc object " + i + ": "+ 
                            matches.items[i].service);
       }
       System.out.println ("*-----------------------------------------*");
      } catch (Exception e) { 
       System.out.println ("EchoServer: EchoServer.main(): Exception "); 
       e.printStackTrace ();
      }
     }
    } 
    

    Listing 6: The Echo Jini service class

    The echo client

    The listing for the client is shown in the following Listing 7. In our main() method, we first set the security manager. We find the Jini Lookup service (reggie) and print its location. We also get the Lookup service’s ServiceRegistrar (the class by which interaction with the Lookup service is possible). Perform a search on the Lookup server to find the service that has the name attribute of “EchoServer.” The Lookup service returns an interface object to the service. If the correct object was returned, call one of its methods.

    import net.jini.core.entry.*; 
    import net.jini.core.lookup.*; 
    import net.jini.core.discovery.*; 
    import net.jini.lookup.*; 
    import net.jini.lookup.entry.*; 
    import net.jini.discovery.*; 
    import java.rmi.*; 
    
    // EchoClient -- The Jini Client Class 
    class EchoClient { 
     
     public static void main (String[] args) { 
      
      int iPort; 
      String sHost; 
      Entry[] aeAttributes; 
      LookupLocator lookup; 
      ServiceID id; 
      ServiceRegistrar registrar; 
      ServiceTemplate template; 
      EchoInterface myServerInterface; 
      try { 
       /* 
        * Setting the security manager to allow the RMI class loader 
        * to go to the codebase for classes that are not available 
        * locally. 
        * ========================================================== */ 
       System.setSecurityManager (new RMISecurityManager ()); 
       
       /* 
        * Find the Jini lookup service (reggie) and print its location. 
        * ============================================================= */ 
       lookup = new LookupLocator ("jini://" + args[0]); 
       sHost = lookup.getHost (); 
       iPort = lookup.getPort (); 
       System.out.println (); 
       System.out.println ("client: LookupLocator = " + lookup); 
       System.out.println ("client: LookupLocator.host = " + sHost); 
       System.out.println ("client: LookupLocator.port = " + iPort); 
       
       /* 
        * Get the lookup service's ServiceRegistrar (the class by which 
        * interaction with the lookup service is possible). 
        * ============================================================= */ 
       registrar = lookup.getRegistrar (); 
       id = registrar.getServiceID (); 
       System.out.println ("client: ServiceRegistrar = " + registrar); 
       System.out.println ("client: ServiceID = " + id); 
       
       /* 
        * Perform a search on the lookup server to find the service 
        * that has the name attribute of "EchoServer". The lookup 
        * service returns an interface object to the service. 
        * ========================================================= */ 
       aeAttributes = new Entry[1]; 
       aeAttributes[0] = new Name ("EchoServer"); 
       template = new ServiceTemplate (null, null, aeAttributes); 
       myServerInterface = (EchoInterface) registrar.lookup (template); 
       System.out.println ("client: ServiceTemplate = " + template); 
       System.out.println ("client: Service object = " +
                           myServerInterface); 
       
       /* 
        * If the correct object was returned, call one of its methods. 
        * ============================================================ */ 
       if (myServerInterface instanceof EchoInterface) { 
        long startTime = System.currentTimeMillis(); 
        System.out.println ("client: Time at server is " + startTime); 
        String message = myServerInterface.echoMessage (args[1]);
        long stopTime = System.currentTimeMillis(); 
        System.out.println ("client: Time at client is " + stopTime); 
        float difference= stopTime-startTime; 
        System.out.println ("client: The Server echoed thus --->" 
                            + message); 
        System.out.println ("client: Time for message to traverse"+
                            "the net is --->" 
                            + difference + " msecs<---"); 
       } 
      } catch (Exception e) { 
       System.out.println ("client: EchoClient.main() exception: "); 
       e.printStackTrace ();
      } 
     } 
    } 
    

    Listing 7: The EchoClient class

    Compile the sources, generate stubs and skeletons, and run the server.

    F:\MyProjects\EchoService>javac *.java
    F:\MyProjects\EchoService>rmic EchoServer
    F:\MyProjects\EchoService>start java -jar c:\files\jini1_0\lib\tools.jar -port 8080 -dir C:\files\jini1_0\lib -verbose
    F:\MyProjects\EchoService>start rmiregistry
    F:\MyProjects\EchoService>start rmid
    F:\MyProjects\EchoService>java -jar -Djava.security.policy=c:\files\jini1_0\example\lookup\policy.all
    c:\files\jini1_0\lib\reggie.jar http://localhost:8080/reggie-dl.jar C:\files\jini1_0\example\lookup\policy.all
    reggie_log public
    using absolute dbdir path: F:\MyProjects\EchoService\reggie_log
    F:\MyProjects\EchoService>java -Djava.security.policy=c:\files\jini1_0\example\lookup\policy.all -Djava.rmi.server.codebase=
    http://localhost/ EchoServer localhost
    EchoServer: JoinManager = com.sun.jini.lookup.JoinManager@1fcdd4c7
    EchoServer: LookupLocator = jini://localhost/
    EchoServer: LookupLocator.host = localhost
    EchoServer: LookupLocator.port = 4160
    EchoServer: ServiceRegistrar = com.sun.jini.reggie.RegistrarProxy@ee58c3bf
    EchoServer: ServiceID = 191ef071-155c-4e2f-a94c-88304b56f5d1
    EchoServer: ServiceMatches = net.jini.core.lookup.ServiceMatches@f41dd4c7
    EchoServer: num matches = 2
    EchoServer: svc item 0: net.jini.core.lookup.ServiceItem@10e1d4c7
    EchoServer: svc object 0: com.sun.jini.reggie.RegistrarProxy@ee58c3bf
    EchoServer: svc item 1: net.jini.core.lookup.ServiceItem@439d4c7
    EchoServer: svc object 1: EchoServer_Stub[RemoteStub [ref: [endpoint:[130.151.68.179:3649](remote),objID:[0]]]]
    *-----------------------------------------*
    ============================================================
    EchoServer: The method echoMessage() in EchoServer was called
    EchoServer: Client says :Hello... This is Gopalan
    ============================================================
    ============================================================
    EchoServer: The method echoMessage() in EchoServer was called
    EchoServer: Client says :Hi Athul...
    ============================================================
    ============================================================
    EchoServer: The method echoMessage() in EchoServer was called
    EchoServer: Client says :Hi Sumithra...
    ============================================================
    

    Run multiple client sessions. The letters shown in boldface font are what you type in.

    C:\jini\EchoServer\EchoService>java -Djava.security.policy=c:\files\jini1_0\example\lookup\policy.all
    -Djava.rmi.server.codebase=http://130.151.68.179/ EchoClient 130.151.68.179 "Hello... This is Gopalan"
    client: LookupLocator = jini://130.151.68.179/
    client: LookupLocator.host = 130.151.68.179
    client: LookupLocator.port = 4160
    client: ServiceRegistrar = com.sun.jini.reggie.RegistrarProxy@b5244982
    client: ServiceID = e78354c2-3881-4079-8a5a-bfafe07ce296
    client: ServiceTemplate = net.jini.core.lookup.ServiceTemplate@1f21d3
    client: Service object = EchoServer_Stub[RemoteStub [ref: [endpoint:[130.151.68.179:3813](remote),objID:[42ed2864:d7106f929a:-8000, 0]]]]
    ============================================================
    client: Time at server is 923695814890
    client: Time at client is 923695814930
    client: The Server echoed thus --->Hello... This is Gopalan
    client: Time for message to traverse the net is --->40.0 msecs<---
    ============================================================
    C:\jini\EchoServer\EchoService>java -Djava.security.policy=c:\files\jini1_0\example\lookup\policy.all
    -Djava.rmi.server.codebase=http://130.151.68.179/ EchoClient 130.151.68.179 "Hi Athul..."
    client: LookupLocator = jini://130.151.68.179/
    client: LookupLocator.host = 130.151.68.179
    client: LookupLocator.port = 4160
    client: ServiceRegistrar = com.sun.jini.reggie.RegistrarProxy@b5244982
    client: ServiceID = e78354c2-3881-4079-8a5a-bfafe07ce296
    client: ServiceTemplate = net.jini.core.lookup.ServiceTemplate@1f3ba4
    client: Service object = EchoServer_Stub[RemoteStub [ref: [endpoint:[130.151.68.179:3813](remote),objID:[42ed2864:d7106f929a:-8000, 0]]]]
    ============================================================
    client: Time at server is 923698395130
    client: Time at client is 923698395140
    client: The Server echoed thus --->Hi Athul...
    client: Time for message to traverse the net is --->10.0 msecs<---
    ============================================================
    C:\jini\EchoServer\EchoService>java -Djava.security.policy=c:\files\jini1_0\example\lookup\policy.all
    -Djava.rmi.server.codebase=http://130.151.68.179/ EchoClient 130.151.68.179 "Hi Sumithra..."
    client: LookupLocator = jini://130.151.68.179/
    client: LookupLocator.host = 130.151.68.179
    client: LookupLocator.port = 4160
    client: ServiceRegistrar = com.sun.jini.reggie.RegistrarProxy@b5244982
    client: ServiceID = e78354c2-3881-4079-8a5a-bfafe07ce296
    client: ServiceTemplate = net.jini.core.lookup.ServiceTemplate@e33b97
    client: Service object = EchoServer_Stub[RemoteStub [ref: [endpoint:[130.151.68.179:3813](remote),objID:[42ed2864:d7106f929a:-8000, 0]]]]
    ============================================================
    client: Time at server is 923698442298
    client: Time at client is 923698442328
    client: The Server echoed thus --->Hi Sumithra...
    client: Time for message to traverse the net is --->30.0 msecs<---
    ============================================================
    C:\jini\EchoServer\EchoService>
    

    The distributed Programming Model

    The Programming Model is used by Clients to enlist the help of Jini services in achieving the client’s goal. It consists of support for leasing, distributed events, and transactions.

    Leasing

    Access to any service is done through a leasing model, which imposes a time limit for the use of the service. This enabling any existing object references to be reclaimed safely in the case of network failures. Persistence of the held reference depends on renewed proof of interest expressed by renewing a lease. Lease holders can safely crash, get disconnected, or simply forget about a leased resource. Leases can be exclusive, thus effectively locking the service from use by others or it can allow multiple requesting services to share a given service. Once the lease expires, the service cannot be used by any other unless the lease is renewed.

    In a distributed Jini system, the client “holder” requests a lease from a “grantor.” The holder may negotiate a lease duration. The grantor decides whether to grant the lease for that lease duration. The grantor may then send the holder a Lease object. The Lease may be exclusive or nonexclusive. The grantor agrees to keep the resource available, to the best of its ability, until the lease is cancelled or expires. If the lease is cancelled or expires, the holder can dispose of the resource.

    Distributed events

    Jini enables communication between resources and services via an event notification mechanism derived from the JavaBeans event model. This distributed event model allows services to register with each other and receive notification—even across machine boundaries—in response to specific actions. The Event Generator generates remote events upon abstract state changes. The Event Listener registers interest in being notified of the abstract state changes in the Event Generator. The registration of the interest is lease-based. The remote event is passed from the Event Generator to the notify() method of the registered Event Listeners. Each RemoteEvent object contains an identifier for the kind of event, a reference to the Event Generator, a sequence number, and an object that was passed in as part of the registration of interest in the event. Objects that want to receive notification of a remote event, implement the RemoteEventListener interface. Unlike JavaBean events, Jini events are identified by an event identifier and the event source. An UnknownEventException is thrown if the event is unrecognizable.

    Transactions

    A transaction is essentially multiple atomic operations that can be treated as a single unit. The transaction is successful or can be committed, only if each of the discrete statements succeeds; it aborts if any one of those statements fail. The Jini transaction system is based on the two-phased commit model, which saves the system’s state before and after the transaction is executed. Thus, if the transaction aborts, the system can perform a rollback or recreate the state the way it was before the transaction was initiated.

    Jini transactions are managed and completed by the TransactionManager. The client hands a factory method a TransactionManager reference and a lease duration. The client receives a new Transaction object and a Lease object from the factory method. The client passes this Transaction object to participants when asking a participant to do a task “under the transaction.” Participants must “join” the transaction before performing the task. If a client or a participant “aborts” the transaction, the TransactionManager instruct all participants to “rollback.” If a client or a participant “commits” the transaction, the TransactionManager queries all participants. If all participants report either “prepared” or “no-change,” the TransactionManager instructs all participants to “roll forward”.

    Comparing Jini with RMI

    Although Jini technology has a lot in common with RMI, there are some important differences nonetheless. Table 1 draws a comparison between the main features of both technologies.

    Table 1: Comparing Java/RMI and Jini

    Java/RMI Jini
    The service storing information about other service providers is the RMI registry. In Jini, the service storing information about other service providers is called Jini Lookup service.
    RMI clients use the class Naming.Lookup() for locating the requested RMI service. Jini clients use the discovery process to locate Jini Lookup services. Discovery is done through multicast requests to well-known addresses or ports.
    The RMI client must know the RMI registry host explicitly. The same rule applies to RMI servers. The Jini clients search for the Jini service without any service hosting knowledge.
    The approach is more rigid because the client is dependent on a particular service provider. The approach is more tolerant to service provider’s faults and maximizes client independence on a particular service provider.
    The RMI proxy-stub approach is strictly adhered to. The Jini proxy concept is more protocol-independent because it does not rely on generated fixed-protocol stubs. The proxy fulfills requests by itself or uses either an RMI call or an internal proxy provider to fulfill a request..
    No concept of built-in support for transactions, distributed events, or leasing. Programming model provides for support for transactions, distributed events, and leasing.

    Applying Jini technology

    What’s possible with Jini? Consider the following scenario:

    Assume your federation is on an enterprise WAN. Now, a colleague of yours looking at a spreadsheet halfway around the world, can easily print out a copy on the printer next to your desk. If this does not sound too impressive, consider the possibility that you may have just plugged in your Jini-enabled printer into the federation while you were on the phone with him—without any printer configuration or messy driver installation.

    Although Jini technology may sound futuristic, it is both a reality and currently being beta tested by about 30 companies worldwide, including market leaders like Canon, Toshiba, Ericsson, Mitsubishi, Epson, and Quantum among others. Jini is not part of Java 2, but Sun is considering making the Jini code freely available in the future by placing it in the public domain.

    Author Bibliography

    Gopalan Suresh Raj is a Senior Analyst, Software Architect, and Developer with expertise in multi-tiered systems development, enterprise service architectures, and distributed computing. He is also an active author, including contributions to Professional JMS Programming, Wrox Press, 2001, Enterprise Java Computing-Applications and Architecture, Cambridge University Press, 1999, and The Awesome Power of JavaBeans, Manning Publications Co., 1998. He has submitted papers at international fora, and his work has been published in numerous technical journals. Visit him at his Web Cornucopia© site (webcornucopia.com) or mail him at gopalan@webcornucopia.com.

    Back