CONTENT | PREV | NEXT

2 Remote Method Invocation (RMI)

2.1 Was ist RMI ?

Definitionen:

Ein entferntes Objekt (remote object) ist ein Objekt, dessen Methoden von einer anderen Java Virtual Machine aus aufgerufen werden koennen. Ein solches Objekt wird durch ein oder mehrere entfernte Schnittstellen (remote interfaces) beschrieben.

Unter Remote Method Invocation versteht man den Aufruf einer Methode eines entfernten Objektes. Der Methodenaufruf auf einem entfernten Objektes folgt dabei derselben Syntax wie der Aufruf einer lokalen Methode.

RMI Inheritance

Hauptziele:

Weiterführende Ziele:

 

Anforderungen an verteilte RMI Anwendungen

 
RMI Components
 

2.2 Step by step

  1. Definition des Remote Interfaces

  2.  
    public interface Server extends Remote {  
       
        public void store(Person p) throws RemoteException;  
        public void delete(Person p) throws RemoteException;  
        public Vector getAll() throws RemoteException;  
       
    }
    rmibase/Server.java
     
  3. Implementierung des Remote Interfaces

  4.  
     
    public class ServerImpl extends UnicastRemoteObject implements Server {  
       
        private Vector persons; //stores all datasets  
       
        public ServerImpl() throws RemoteException {  
            super();  
            persons=new Vector();  
        }  
       
        public synchronized void store(Person p) throws RemoteException {  
       
            //add person p to the database  
            //if p already exists update dataset  
           int pos=persons.indexOf(p);  
           if (pos == -1) {  
               persons.addElement(p);  
           } else {  
               persons.setElementAt(p,pos);  
           }  
       
        }  
       
        public synchronized void delete(Person p) throws RemoteException {  
       
            //remove person p from the database  
            //if p does not exist do nothing  
            persons.removeElement(p);  
       
        }  
       
        public synchronized Vector getAll() throws RemoteException {  
       
            //return a whole copy of the database  
            //do not care about performance ;)  
            return persons;  
       
        }  

    }

    rmibase/ServerImpl.java
     
  5. Erzeugung der Stub und Skeleton Klassen (rmic)

  6.  
  7. Registrierung des Remote Object

  8.  
     
    public static void main(String[] args) {  
       
        System.setSecurityManager(new RMISecurityManager());   

        try {  

            //create the implementation object  
            ServerImpl server=new ServerImpl();  
       
            //bind the implementation object to a logical name  
            //register it  
            String url="rmi://"+InetAddress.getLocalHost().getHostName()+"/EMailBase";  
            Naming.rebind(url,server);  
       
        } catch (java.io.IOException e) {  
            System.err.println("server initialization failed");  
            System.exit(1);  
        }  
       
    }

     
  9. Implementierung eines Clients

  10.  
     
    public class Client {  
       
        Server serverRef; //remote reference to the server  
       
        public Client(Server serverRef) {  
            this.serverRef=serverRef;  
            ...  
        }  
       
        void store(String name, String firstName, String eMail) {  
        
            try {  
         
                //create new person and store it  
                Person p=new Person(name,firstName,eMail);  
                serverRef.store(p);  
         
            } catch (RemoteException e) {  
                handleRemoteException(e);  
            }  
        
        }  
       
        void delete(String name, String firstName) {  
        
            try {  
         
                //create person object for lookup  
                //and delete it  
                Person p=new Person(name,firstName,null);  
                serverRef.delete(p);  
         
            } catch (RemoteException e) {  
                handleRemoteException(e);  
            }  

        }  
       
        Vector getAll() {  
        
            Vector persons;  
            try {  
         
                //get all persons  
                persons=serverRef.getAll();  
         
            } catch (RemoteException e) {  
                handleRemoteException(e);  
                persons=new Vector();  
            }  
            return persons;  
        
        }  
       
        ...  

        public static void main(String[] args) {  
        
            try {  
         
                //resolve server reference  
                Server serverRef=(Server)Naming.lookup(args[0]);  
        
                //start client  
                Client client=new Client(serverRef);  

            } catch (Exception e) {  
                System.out.println(e.getMessage());  
            }  
        
        }  
       
    }

    rmibase/Client.java
     
  11. Start der rmiregistry

  12.  
  13. Start des Servers

  14.  
  15. Start des Clients
 

2.3 Spezielle Features

2.3.1 Dynamic Class Loading

Klassen, welche bei Methodenaufrufen als Parameter oder Rueckgabewerte dienen, koennen bei Bedarf von per URL (http, ftp, file) automatisch nachgeladen werden.

-> Server kann Aufgaben erledigen, welche zur Compile- oder Startzeit noch gar nicht definiert waren
 
 Anwendungsbeispiel:
// Remote interface for a server that can execute different tasks.  
public interface ComputeServer extends Remote {  

    public Object executeTask(Task t) throws RemoteException;  

 

// A task has to implement this interface.  
// Its code is described in the execute() method.  
public interface Task extends Serializable {  

    public Object execute();  

}

 

2.3.2 Remote Object Activation

Aktivierung und Shutdown von Remote Objects bei Bedarf

-> effiziente Ressourcennutzung
 
 
public class ActivatableServerImpl extends Activatable implements Server { 
  
    private Vector persons; //stores all datasets 
  
    public ActivatableServerImpl(ActivationID id, MarshalledObject data)  
        throws RemoteException { 
   
        super(id,0); 
        persons=new Vector(); 
   
    } 
  
    public synchronized void store(Person p) throws RemoteException { ... } 
    public synchronized void delete(Person p) throws RemoteException { ... } 
    public synchronized Vector getAll() throws RemoteException { ... } 
  
    public static void main(String[] args) { 
   
        System.setSecurityManager(new RMISecurityManager());  

        try { 

            // Properties that replaces rmid's system properties 
            Properties props=new Properties(); 
            props.setProperty("java.security.policy","file:rmibase/policy.txt"); 
    
            // Create an ActivationGroupDesc that contains all information 
            // that rmid will require 
            ActivationGroupDesc.CommandEnvironment ace = null;  
            ActivationGroupDesc exampleGroup = new ActivationGroupDesc(props, ace); 
    
            // Once the ActivationGroupDesc has been created, register it  
            // with the activation system to obtain its ID 
            ActivationGroupID agi =  
                ActivationGroup.getSystem().registerGroup(exampleGroup); 
    
            // Now explicitly create the group 
            ActivationGroup.createGroup(agi, exampleGroup, 0); 
    
            // Codebase 
            String location = "file:./";  
    
            // Create the rest of the parameters that will be passed to  
            // the ActivationDesc constructor  
            MarshalledObject data = null;  
    
            // The second argument to the ActivationDesc constructor will be used  
            // to uniquely identify this class; it's location is relative to the  
            // URL-formatted String, location.  
            ActivationDesc desc =  
                new ActivationDesc ("rmibase.ActivatableServerImpl", location, data); 
     
            // Create an remote instance 
            // Register the activation decriptor with rmid 
            Server server = (Server)Activatable.register(desc);  

            // Bind the interface in the RMI registry 
            Naming.rebind("EMailBase",server); 
    
       } catch (Exception e) { 
            System.err.println("activation setup failed"); 
            System.exit(1); 
       } 

       System.exit(0); 

   } 

}

 rmibase/ActivatableServerImpl.java
 

2.3.3 RMI über Firewalls

Normalerweise versucht RMI direkte TCP Verbingungen zu entfernten Objekten aufzubauen. Firewalls erlauben dies nicht.

-> Einbettung des RMI Aufrufs in einen HTTP-POST Request, Antwort im Body des HTTP Responses

2 Varianten:

  1. HTTP Proxy kann Requests direkt an RMI Server Port weiterleiten. -> RMI Server Socket versteht RMI Calls in HTTP-POST Requests und beantwortet diese.
  2. HTTP Proxy forwarded nur zu bestimmten Ports (z.B. Port 80). -> CGI Skript auf Zielmaschine wird RMI Calls an RMI Server Socket weiterleiten.
 
© 1998 sven.buergel@informatik.tu-chemnitz.de
CONTENT | PREV | NEXT