Distributed Objects and JAVA

Preview:

Citation preview

Distributed Objects and JAVA

• Overview of distributed object programming

• In-depth discussion of JAVA’s remote method invocation package with examples.

• Initially an introduction to RMI.• Examples, illustrate features of RMI.

What is RMI?• RMI is a powerful technology for developing

networked applications.• RMI transcends client/server model of computing

with the remote object model.• Servers define object that clients can use remotely.• Clients invoke methods of remote objects

transparently (once located). • Arguments/return values can be primitive values

or any serializable object.

Limitations of RMI!

• Both client and server must be JAVA applications!

• Not as general as CORBA architecture.• Limitations are being over come by RMI-

IIOP infrastructure.

Developing an RMI Application

• Create an interface that extends java.rmi.Remote interface.

• Defines the exported methods that a remote object implements.

• Each method in the interface MUST be declared to throw java.rmi.RemoteException.

• Necessary to handle errors with network connections and server problems.

Developing RMI Apps ...

• The (server) class that implements the Remote interface must be a subclass of java.rmi.server.UnicastRemoteObject.

• Remote methods are declared to throw RemoteException objects.

• UnicastRemoteObject and the RMI infrastructure handles everything else ...

Developing RMI Apps ...• A (server) program creates an instance of the

remote object.• Register the object by name with a registry service

(this exports the object, making it available for use by clients), such as the java.rmi.Naming class and the rmiregistry program.

• A server programs can act as its own registry server thro’ LocateRegistry class and the Registry interface of the java.rmi.registry package.

• Compile the server program (javac). • rmic -- generates stub and a skeleton for the remote object.• Client’s reference to a remote object is implemented as an

instance of a stub class.• Stub does the necessary networking to pass a method

invocation onto a skeleton class on the server.• Skeleton translates the networked request into a method

invocation on the server object and passes the return value back to the stub.

• Stub then passes return value back to the client.• rmic tool hides the details of generating stubs and

skeletons from the programmer (similar to rpcgen).• rmic generate classes with the suffixes __Stub and

__Skel.• Servers using the default registry service (provided

by the Naming class) require users to run the registry server (invoke rmiregistry program).

• Client programs use the remote object exported by the server.

• Clients obtain a reference to the remtoe object using the Naming class to look up the object by name.

• Name is typically an rmi: URL.• The remote reference obtained is an instance of the

Remote interface for the object (actually a stub object).• Client can then invoke methods on this remote reference

transparently, except that all remote methods might throw RemoteException objects.

• RMI uses the JAVA serialisation mechanism to transfer the stub object from the server to the client.

• Security manager objects should be installed to prevent the loading of an untrusted stub object from causing harm (RMISecurityManager class is suitable).

• Finally, start the server and run the client.

RMI Hello World Examplepackage message;import java.rmi.*;

/* This interfaces defines the exported methods */ public interface RemoteHelloWorld extends Remote { public String sayHello () throws RemoteException();}

package client;import java.rmi.*; import java.rmi.server.*; import message.*;public static class Client { public static void main(String []args) { try{ System.setSecurityManager(new RMISecurityManager()); //Read a system property, specified on command line with -D // to determine host String url = System.getProperty(“myserver”,”rmi:///HELLO”); RemoteHelloWorld server =

(RemoteHelloWorld) Naming.lookup(url); String value = server.sayHello(); System.out.println(value); }catch(RemoteException e) { System.err.println(e);} catch(Exception e) { System.err.println(e); System.err.println(“USAGE: java [-Dmyserver=url>]”); } }}

% javac HelloWorld.java% rmic -d . server.HelloWorld% rmiregistry &% java HelloWorldpackage server;import java.rmi.*; import java.rmi.server.*; import message.*;import java.rmi.registry.*;public class HelloWorld extends UnicastRemoteObject implements RemoteHelloWorld { String sayHello() throws RemoteException{ return “Hello World”;} public static void main(String []args) { try{ HelloWorld theObject= new HelloWorld(); Naming.rebind(String(“HELLO”),theObject); System.out.println(“HELLO is now up and running”); }catch(Exception e){ …} }}

RMI and JAVA 1..2

• JAVA 2 requires a (security ) policy file.• java -Djava.security.manager -

Djava.security.policy=policy server.HelloWorld

• java -Djava.security.policy=policy client.Client

Policy file

grant { permission java.net.SocketPermission “*:1024-65535”, “accept, connect, listen, resolve”;}grant { permission java.lang.RuntimePermission “createSecurityManager”;};

Bi-directional Messaging

• Extend the ideas of the previous example so that Clients are registered with the Server.

• Means that the Server can call back to Clients.

• Simple GUI is added to allow the use to type and see messages being typed by other Clients.

• Client registers with the Server.• Server stores the Client object in a hash

table.• Client sends a message to the Server that

forwards the message to each object in the hash table.

• Creates a simple networked chat program.

Message Packagepackage message;import java.rmi.*;public interface interface MessageReceiver extends Remote { void print (String s) throws RemoteException; }

public interface MessageServer extends Remote { static String SERVER_NAME = “MessageServer”; static int FAILURE = -1; static int SUCCESS = 0;

void send(String name,String s) throws RemoteException; int register(String name,MessageReceiver m) throws RemoteException;}

Server Packagepackage server; import java.util.Enumeration; import java.util.HashTable; import java.rmi.*; import java.rmi.server.*;import java.rmi.registry.*; import message.*;

public class Server extends UnicastRemoteObject implements MessageServer { static HashTable receivers = new HashTable(5); public Server() throws RemoteException { super();} public void send(String name, String s) throws RemoteException { for(Enumeration e = receivers.elements(); e.hasMoreElements();) { MessageReceiver m = (MessageReceiver) e.nextElement(); m.print(name + “: “ + s); } }

public int register( String name, MessageReceiver m) { int retval = MessageServer.FAILURE; if((name != null) && (m != null)) { if(receivers.get(name) == null) { receivers.put(name,m); System.out.println(“Added “ + name); retval = MessageServer.SUCCESS; }else { System.out.println(“Client not added because “ + name + “ already exists on Server”); } } return retval; }public static void main(String []args) { System.setSecurityManager(new RMISecurityManager()); try { MessageServer server = new Server(); // Bootstrap PRIVATE registry! Registry reg = LocateRegistry.createRegistry( Registry.REGISTRY_PORT); reg.rebind(MessageServer.SERVER_NAME,server); System.out.println(“Server bound and started”); } catch(Exception e) { …} } }

Client packagepackage client; import java.awt.*; import java.awt.event.*; import java.rmi.*; import java.rmi,.server.*; import message.*;public class Client extends Frame implements MessageReceiver, ActionListener, WindowListener { TextField tf; TextArea ta; static String name; static MessageServer server;public Client() throws RemoteException { setTitle(name); setLayout(new BorderLayout()); tf = new TextField(30); tf.addActionListener(this); add(“South”,tf); ta = new TextArea(20,20); addWindowListener(new WindowCloser()); UnicastRemoteObject.exportObject(this); // accept remote calls!}

public void actionPerformed(ActionEvent ae) { try { server.send(name,tf.getText()); }catch Exception e) { …}}public void print(String s) { ta.append(s+”\n”);}public static void main(String args[]) { if(args.length < 1) { System.out.println(“USAGE: java client.Client NAME”); System.exit(-1); } name = args[0]; System.setSecurityManager(new RMISecurityManager()); try { Client cf = new Client(); cf.pack();cf.show(); server =(MessageServer) Naming.lookup(MessageServer.SERVER_NAME); int s = server.register(args[0],cf); if(s == MessageServer.FAILURE) throw new Exception(“Could not Connect to SERVER”); } catch(Exception e) {… System.exit(-1);}}}

Class Loading

• Dynamically load class code.• java.rmi.server.codebase property.• Properties sysProps; sysprops =

System.getProperties(); sysProps.put(“java.rmi.server.codebase”,aString);system.setProperties(sysProps);

• grant { permission java.security.AllPermission;}; WARNING!!!

Why do we need class loading?

• Not all class files are available on all hosts (machines).

• If your application involves remote agents running on hosts not under your control.

Configuration for class loading

RMI runtime includes an URL for marshalled data/objects.

Receiving process then knows where to locate a marshalled object’s byte code (CLASS).

IF the class for the object being marshalled was loaded by a non default class loader, then the codebase of that particular loader is encoded in the marshalled stream.

ELSE the class were loaded using the default loader from the local CLASSPATH then the value of java.rmi.server.codebase is sent.

• If an RMI system attempts to unmarshal some data/object and the class is not found by the default loader.

• RMIClassLoader can use URL in stream to look for class bytecodes directly.

• Unmarshal operation will generate an exception if the class cannot be found.

• Must have a security manager installed for remote class loading!

• permission java.net.SocketPermission “myhost.cs.tcd.ie”, “accept,connect”;

Garbage Collection• Normally don’t have to worry! Automatic process.• Every server that contains RMI-exported objects

automatically maintains a list of remote references to the objects it serves

• List is maintained explicitly through registry/naming service, or implicitly as the result of a remote method call.

• Each client is issued a remote object reference through the remote reference layer.

• Record of this object is in the form of an expirable lease on the object.

Garbage Collection

• When client is finished with the reference and allows the remote stub to go out of scope, or lease expires.

• Reference layer (hosts) then deletes the record of the remote reference and notifies the client’s reference layer that the remote reference has expired.

• Concept of expirable leases is used to deal with situations where client-side or network failure prevents a client from notifying a server that is done with its reference to an object.

• Server may require notification when client exits/disconnects.• Remote objects can implement java.rmi.server.Unreferenced interface.• Single method unreferenced.• unreferenced method is sent to the server when no more clients hold

references to a remote object.• Default behaviour, unreferenced will be received when no clients have

accessed a remote object for 10 mins, when all stub files are finalized.• Client timeout can be customised by setting java.rmi.dgc.leaseValue

property to the desired number of milliseconds.• Clients can be programmed to initiate the finalize methods on their stub

files (ensure notification happens ASAP).

RMI and FireWalls

• Firewalls are machines/program that prevent certain types of network connections.

• RMI (default) attempts to make direct connections from client to server.

• Firewalls often only allow HTTP connections for web browsing.

• RMI supports use of HTTP. • Various work-arounds in case of firewalls.

Remote Object Activation

• UnicastRemoteObject allows the creation of a remote object that can be accessed from a server program.

• Server program must be accessible at all time to allow client connection.

• Performance hit can be large if many remote object servers must be active!

• Java2 introduces the notion of activation. Managed by a small program called rmid that runs on the server.

• Client request a service, rmid starts the remote object and communication starts normally. Many services need only then take up CPU time when the service is actually required!

• rmid must be configured to know where to find your server programs and all remote objects.

Features of RMI Activation Service

• Ability to automatically create remote objects triggered by requests for these objects.

• Support for activation groups, in which groups of activateable remote objects are executed in the same JVM,(auto-start JVM if necessary).

• Ability to restart remote objects if they exit, or are destroyed. Fault-tolerance.

Defining an activatable remote object

• Subclass your remote object implementation from the Activatable class provided in java.rmi.activation package.

• Provide activation contstructors in the server implementation.

• Register the object and its activation method with the activation service.

• Do the lab!

RMI Introduction Summary

• RMI aims to support seamless remote method invocation on objects in different JVMs, also callbacks from servers and applets.

• Debugging: use the flag -Djava.rmi.server.logCalls=true

Recommended