2009-07-27 5 views
8

Ich habe einen Client, der einen langen laufenden Prozess auf dem Server startet. In regelmäßigen Abständen möchte ich dem Benutzer zeigen, was im Hintergrund passiert. Der einfachste Ansatz besteht darin, den Server abzufragen, aber ich frage mich, ob es keine Möglichkeit gibt, das Observer-Muster dafür zu implementieren. Leider benutze ich RMI, um mit dem Server zu sprechen, und ich befürchte, dass ich meinen Client dafür zu einem RMI-Server machen muss.Wie implementiert man das Observer-Muster mit Java RMI?

Gibt es eine andere Möglichkeit, die ich vermisse?

+1

gibt Ich versuche, dies auch zu tun, und ich kam zu dem gleichen Schluss ... rmi saugt irgendwie! :) – JohnIdol

Antwort

1

Ich glaube nicht, dass Sie etwas verpassen. Die einzigen beiden Möglichkeiten bestehen darin, den Server entweder regelmäßig aufzurufen und den Status zu überprüfen (Polling) oder einen Rückruf zu registrieren, den der Server regelmäßig aufruft (Ihr Client muss eine Methode verfügbar machen). IMO, Polling ist ein durchaus vernünftiger Weg, damit umzugehen.

3

RMI kann im Allgemeinen Zwei-Wege-Kommunikation unterstützen. (Und ja, RMI ist ein PITA einzurichten und alles andere mit.)

Allerdings unterstützt der HTTP-Transport, der über ein CGI-Skript (!) Funktioniert nicht.

+0

Ist das immer noch wahr, wenn ich den Server in meinem Code mit LocateRegistry.createRegistry() starte (anstatt die ausführbare Datei von Sun zu verwenden)? –

+0

+1 für "(Und ja, RMI ist ein PITA einzurichten und alles andere mit zu tun.)" Bitte sag meiner Schule, dass. – Luc

2

alle Antworten Konsolidieren hier implementierte I 2-Wege-RMI zwischen Client und Server mit Server seine Stub Belichtungs Registry mit

  1. Der Client einen Stub des Servers, von RMI-Registry wird
  2. Dann wird der Kunde legt seine Stub als Beobachter an den Methode addObserver Servers
  3. der Server die Clients mit dieser Stub
  4. benachrichtigt

Der folgende Code wird eine bessere Idee

import java.rmi.*; 
import java.rmi.registry.*; 
import java.rmi.server.*; 
import java.util.Observable; 
import java.util.Observer; 
import java.net.*; 

import javax.rmi.ssl.SslRMIClientSocketFactory; 
import javax.rmi.ssl.SslRMIServerSocketFactory; 

interface ReceiveMessageInterface extends Remote 
{ 
    /** 
    * @param x 
    * @throws RemoteException 
    */ 
    void receiveMessage(String x) throws RemoteException; 

    /** 
    * @param observer 
    * @throws RemoteException 
    */ 
    void addObserver(Remote observer) throws RemoteException; 
} 

/** 
* 
*/ 
class RmiClient extends UnicastRemoteObject 
{ 
    /** 
    * @param args 
    */ 
    static public void main(String args[]) 
    { 
     ReceiveMessageInterface rmiServer; 
     Registry registry; 
     String serverAddress = args[0]; 
     String serverPort = args[1]; 
     String text = args[2]; 
     System.out.println("sending " + text + " to " + serverAddress + ":" + serverPort); 
     try 
     { // Get the server's stub 
      registry = LocateRegistry.getRegistry(serverAddress, (new Integer(serverPort)).intValue()); 
      rmiServer = (ReceiveMessageInterface) (registry.lookup("rmiServer")); 

      // RMI client will give a stub of itself to the server 
      Remote aRemoteObj = (Remote) UnicastRemoteObject.exportObject(new RmiClient(), 0); 
      rmiServer.addObserver(aRemoteObj); 

      // call the remote method 
      rmiServer.receiveMessage(text); 
      // update method will be notified 
     } 
     catch (RemoteException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (NotBoundException e) 
     { 
      System.err.println(e); 
     } 
    } 

    public void update(String a) throws RemoteException 
    { 
     // update should take some serializable object as param NOT Observable 
     // and Object 
     // Server callsbacks here 
    } 
} 

/** 
* 
*/ 
class RmiServer extends Observable implements ReceiveMessageInterface 
{ 
    String address; 
    Registry registry; 

    /** 
    * {@inheritDoc} 
    */ 
    public void receiveMessage(String x) throws RemoteException 
    { 
     System.out.println(x); 
     setChanged(); 
     notifyObservers(x + "invoked me"); 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    public void addObserver(final Remote observer) throws RemoteException 
    { 
     // This is where you plug in client's stub 
     super.addObserver(new Observer() 
     { 
      @Override 
      public void update(Observable o, 
       Object arg) 
      { 
       try 
       { 
        ((RmiClient) observer).update((String) arg); 
       } 
       catch (RemoteException e) 
       { 

       } 
      } 
     }); 
    } 

    /** 
    * @throws RemoteException 
    */ 
    public RmiServer() throws RemoteException 
    { 
     try 
     { 
      address = (InetAddress.getLocalHost()).toString(); 
     } 
     catch (Exception e) 
     { 
      System.out.println("can't get inet address."); 
     } 
     int port = 3232; 
     System.out.println("this address=" + address + ",port=" + port); 
     try 
     { 
      registry = LocateRegistry.createRegistry(port); 
      registry.rebind("rmiServer", this); 
     } 
     catch (RemoteException e) 
     { 
      System.out.println("remote exception" + e); 
     } 
    } 

    /** 
    * 
    * @param args 
    */ 
    static public void main(String args[]) 
    { 
     try 
     { 
      RmiServer server = new RmiServer(); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
    } 
} 
+0

Basierend auf Ihrem Code kann die RmiClient-Klasse auf dem Server verwendet werden, wenn die RmiServer-Klasse den addObserver-Mechanismus implementiert. Ist das die RmiClient-Klasse, die in dem Client und dem Server definiert wird? – KUN