Exercise 1. JINI

whooshribbitSoftware and s/w Development

Dec 2, 2013 (3 years and 8 months ago)

137 views

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


1.

An understanding about how the Jini framework is designed

2.

An understanding about how a programmer uses this framework.


I.

Introductions (SYS
-
ADMIN): [There is nothing you need to do here]


Framework re
quirements:



A TCP/IP network, all machines having an IP address and a complete TCP
stack with the ability to send and receive multicast messages.


In the shop110 lab, all machines are in the 131.204.139.0 TCP/IP subnet. Machines are
asssigned their IP add
resses 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 Engin
eering’s Domain Name server.




A Jini lookup service in order to participate in the multicast discovery
mechanism.


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.



Rmid is a daemon that provides a JVM from which other JVMs can
be
spawned. It provides support for activation of objects. Prior to Java2.0, an
object could be accessed remotely by a client from a server only if the server
created an instance of the object and then ran continuously. Rmid uses the port
1098 by default
.



The HTTP server listens to a port and can supply (export) files to clients what
make URL requests to this server. A server is provided in the Jini
distribution. The server is running on port 8080 to avoid problems with the
web server running on port 80
.





Steps I took to get a lookup service started were (in this order and used the shop line)


1.

HTTPD


(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/l
ib/tools.jar
-
port 8080
-
dir c:/opt/jini/jini1_0/lib

verbose


2.

RMID


(Windows and shop110ab)


rmid


3.

LOOKUP


(Windows on the machine foo.cse.eng.auburn.edu [with a directory c:
\
temp] )

java
-
Djava.security.policy=c:
\
jini
\
jini1_0
\
example
\
lookup
\
poli
cy


-
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 p
ublic




_____

0. If you want to be a client and not implement a service, jump to step 31.
















II.

A Service:



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 d
irectory 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
direc
tory 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.



chapter5
corejini
service
chapter5
corejini
service-dl
files

_____

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 clien
t by
download.


_____

7. Check your directories and files

HelloWorldServiceInterface.java
chapter5
corejini
HelloWorldServiceInterface.class
chapter5
corejini
service
HelloWorldServiceInterface.class
chapter5
corejini
service-dl
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 typin
g, 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.DiscoveryListe
ner;

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;

im
port 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 Hashtab
le();

// 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 di
scovery. 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 impleme
nts 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(deadreg
s[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
subclas
sing 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(nu
ll, 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. Thu
s, 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);


}


catc
h (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 thre
ad 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.




publ
ic static void main(String args[]) {


try {


HelloWorldService hws =


new HelloWorldService();


new Thread(hws).start();


} catch (IOException ex) {


System.out.println("Couldn't create servic
e: "


+ 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 clas
s 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 u
nix). 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.s
erver.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.















III.

A Client:


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. Wh
en 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.



chapter5
corejini
client
files







_____

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 HelloWorldServ
iceInterface {


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 direc
tories reflecting the packaging have been created by this command.






_____

36. Check your directories and files

HelloWorldServiceInterface.java
chapter5
corejini
HelloWorldServiceInterface.class
chapter5
corejini
client
files





_____ 36. Now we will create the client source HelloWorldClient.java


To avoid a lot of typing, ftp the sourc
e 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 inv
est 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 tem
plate 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 {


pub
lic ServiceID serviceID;


public Class[] serviceType;


public Entry[] attributeSetTemplates; …




_____

42. The lookup service that we discover.



protected LookupDiscovery disco;



_____

43. T
he 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 DiscoveryListen
er {


_____

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() == nu
ll) {


System.setSecurityManager(


new RMISecurityManager());


}





_____

48. Find a lookup service. The null string indicates the public group


// Only search the public group


disco = new Lookup
Discovery(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 (Remote
Exception 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 H
elloWorldServiceInterface.


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


-
classpat
h 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 yo
ur 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 someo
ne 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