Jini for DistJava

Jan Newmarch
jan@newmarch.name
Monash University

Background

Communication

Lookup

OVERVIEW


What is Jini?


Jini Federation


Figure 1: Components of a Jini federation

Service Registration


Figure 2: Querying for a service locator

Figure 3: Registrar returned

Figure 4: Service uploaded

Client Lookup


Figure 5: Querying for a service locator

Figure 6: Registrar returned

Figure 7: Asking for a service

Figure 8: Service returned

Support Services


Proxies


Attribute Registration


Service Location


Leasing


Non-distributed Application


Distributed Version


Client Structure

Internally a client will look like

prepare for discovery
discover a lookup service
prepare a template for lookup search
lookup a service
call the service

Server Structure

prepare for discovery
discover a lookup service
create information about a service
export a service
renew leasing periodically


ENTRIES


Entry class


Creating entries


Interfaces, implementations and entries


SIMPLE SYSTEM

Jini Converter Service


Jini Service Specification


package jini;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Converter extends Remote {
    public float inchToMM(float value) throws RemoteException;
    public float mmToInch(float value) throws RemoteException;
};

Jini Service Implementation


package jini;

public class ConverterImpl implements Converter {
    public float inchToMM(float value) {
	return value * 25.4f;
    }

    public float mmToInch(float value) {
	return value / 25.4f;
    }
};

Jini Server


package jini;

import net.jini.lookup.JoinManager;
import net.jini.core.lookup.ServiceID;
import net.jini.discovery.LookupDiscovery;
import net.jini.core.lookup.ServiceRegistrar;
import java.rmi.RemoteException;
import net.jini.lookup.ServiceIDListener;
import net.jini.lease.LeaseRenewalManager;
import net.jini.discovery.LookupDiscoveryManager;
import net.jini.discovery.DiscoveryEvent;
import net.jini.discovery.DiscoveryListener;
import java.rmi.RMISecurityManager;
import java.rmi.Remote;
import net.jini.jeri.BasicJeriExporter;
import net.jini.jeri.BasicILFactory;
import net.jini.jeri.tcp.TcpServerEndpoint;
import net.jini.export.*; 

public class Server {

    // explicit proxy for Jini 2.0
    protected Remote proxy;
    protected ConverterImpl impl;
    
    public static void main(String argv[]) throws Exception {
	Server server = new Server();

        // stay around forever
	Object keepAlive = new Object();
	synchronized(keepAlive) {
	    keepAlive.wait();
	}
    }

    public Server() throws Exception {
	// Create a service object
	impl = new ConverterImpl();

	// Specify the transport protocol: Jeri over TCP
	Exporter exporter = 
	    new BasicJeriExporter(TcpServerEndpoint.getInstance(0),
				  new BasicILFactory());
	
	// Export the service object. This creates a socket 
	// endpoint to listen for requests and pass them to 
	// the service
	proxy = exporter.export(impl);

	// install suitable security manager to protect
	// against downloaded code
	System.setSecurityManager(new RMISecurityManager());

	// Find LUS's and register the service proxy with them
	JoinManager joinMgr = null;
	LookupDiscoveryManager mgr = 
	    new LookupDiscoveryManager(LookupDiscovery.ALL_GROUPS,
				       null,  // unicast locators
				       null); // DiscoveryListener
	joinMgr = new JoinManager(proxy, // service proxy
				  null,  // attr sets
				  (ServiceIDListener) null,  // ServiceIDListener
				  mgr,   // DiscoveryManager
				  new LeaseRenewalManager());
    }
} // ConverterServer

Jini Client


package jini;

import java.rmi.RMISecurityManager;
import net.jini.discovery.LookupDiscovery;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.discovery.LookupDiscoveryManager;
import net.jini.lookup.ServiceDiscoveryManager;
import net.jini.core.lookup.ServiceItem;
import net.jini.lease.LeaseRenewalManager;

public class Client {

    private static final long WAITFOR = 100000L;

    public static void main(String argv[]) {
	new Client();

        // stay around long enough to receive replies
        try {
            Thread.currentThread().sleep(2*WAITFOR);
        } catch(java.lang.InterruptedException e) {
            // do nothing
        }
    }

    public Client() {

	// Prepare a service description
	Class [] classes = new Class[] {Converter.class};
	ServiceTemplate template = new ServiceTemplate(null, classes, 
						       null);

	// Try to find an LUS and lookup the service
	ServiceDiscoveryManager serviceDiscoveryMgr = null;

	System.setSecurityManager(new RMISecurityManager());

        try {
            LookupDiscoveryManager mgr =
                new LookupDiscoveryManager(LookupDiscovery.ALL_GROUPS,
                                           null, // unicast locators
                                           null); // DiscoveryListener
	    serviceDiscoveryMgr = new ServiceDiscoveryManager(mgr, 
						new LeaseRenewalManager());
	} catch(Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
  
	ServiceItem item = null;
	// Try to find the service, blocking till timeout if necessary
	try {
	    item = serviceDiscoveryMgr.lookup(template, 
					      null, // no filter 
					      WAITFOR); // timeout
	} catch(Exception e) {
	    e.printStackTrace();
	    System.exit(1);
	}

	// We've either found a service or timed out
	if (item == null) {
	    // couldn't find a service in time
	    System.out.println("no service");
	    System.exit(1);
	}

	// Extract the service from the description
	Converter converter = (Converter) item.service;

	if (converter == null) {
	    System.out.println("Converter null");
	    System.exit(1);
	}

	// Now we have a suitable service, use it
	try {
	    System.out.println("2 inches is (mm): " +
			       converter.inchToMM(2.0f));
	    System.out.println("3000mm is (in): " +
			       converter.mmToInch(3000f));
	} catch(java.rmi.RemoteException e) {
	    System.err.println(e.toString());
	}
	System.exit(0);
    }
} // Client


Jini Environment


SECURITY


JDK 1.2 Security


Service requirements


grant {
    permission net.jini.discovery.DiscoveryPermission "*";
    // multicast request address
    permission java.net.SocketPermission "224.0.1.85", "connect,accept";
    // multicast announcement address
    permission java.net.SocketPermission "224.0.1.84", "connect,accept";

    // RMI connections
    permission java.net.SocketPermission "*.dstc.edu.au:1024-", "connect,accept";
    permission java.net.SocketPermission "130.102.176.249:1024-", "connect,accept";
    permission java.net.SocketPermission "127.0.0.1:1024-", "connect,accept";

    // reading parameters
    // like net.jini.discovery.debug!
    permission java.util.PropertyPermission "net.jini.discovery.*", "read";
};

Client requirements

The client is most at risk as it imports remote objects into its address space

Client policy


grant {
    permission net.jini.discovery.DiscoveryPermission "*";

    // multicast request address
    permission java.net.SocketPermission "224.0.1.85", "connect,accept";
    // multicast announcement address
    permission java.net.SocketPermission "224.0.1.84", "connect,accept";

    // RMI connections
    permission java.net.SocketPermission "127.0.0.1:1024-", "connect,accept";
    permission java.net.SocketPermission "*.dstc.edu.au:1024-", "connect,accept";
    permission java.net.SocketPermission "130.102.176.249:1024-", "connect,accept";

    // DANGER
    // HTTP connections - this is where external code may come in - careful!!!
    permission java.net.SocketPermission "127.0.0.1:80", "connect,accept";
    permission java.net.SocketPermission "*.dstc.edu.au:80", "connect,accept";

    // reading parameters
    // like net.jini.discovery.debug!
    permission java.util.PropertyPermission "net.jini.discovery.*", "read";

};

Running things

Jini classes

The common classes needed by all of reggie, the clients and servers are

  1. jsk-lib.jar
  2. jsk-platform.jar
These are not part of standard Java. They must be downloaded from Sun, and are in the Jini lib directory.

Jini Lookup Service

The command Launch-All in the Jini installverify directory will start the needed support services.

Client

The client needs to have the following classes in its CLASSPATH, in addition to the Jini classes

  1. The Converter interface
  2. The class Client

The client can then be run by


java -Djava.security.policy=policy.all Client

Server

The server needs to have the following classes in its CLASSPATH, in addition to the Jini classes

  1. The Converter interface
  2. The class Server
  3. The class ConverterImpl

The server can then be run by


java -Djava.rmi.server.codebase=http://hostname/classes \
     -Djava.security.policy=policy.all \
     Server

Variations

URLs


Jan Newmarch (http://jan.newmarch.name)
jan@newmarch.name
Last modified: Mon Oct 2 14:31:53 EST 2006
Copyright ©Jan Newmarch
Copyright © Jan Newmarch, Monash University, 2007
Creative Commons License This work is licensed under a Creative Commons License
The moral right of Jan Newmarch to be identified as the author of this page has been asserted.