2009-07-27 29 views
8

Ho un client che avvia un processo in esecuzione lungo sul server. A intervalli regolari, vorrei mostrare all'utente cosa sta accadendo in background. L'approccio più semplice è quello di interrogare il server, ma mi chiedo se non ci fosse un modo per implementare il pattern Observer per questo. Sfortunatamente, sto usando RMI per parlare con il server e temo di dover trasformare il mio client in un server RMI per questo.Come implementare il pattern Observer con Java RMI?

C'è un altro modo che mi manca?

+1

che sto cercando di fare anche questo e sono giunto alla stessa conclusione ... rmi kinda succhia! :) – JohnIdol

risposta

1

Non penso che ti manchi qualcosa. Gli unici due modi sono di chiamare periodicamente il server e controllare lo stato (polling) o registrare un callback che il server chiama periodicamente (il client deve esporre un metodo). IMO, il polling è un modo perfettamente ragionevole per gestirlo.

3

RMI può in generale supportare la comunicazione bidirezionale. (E sì, RMI è un PITA da configurare e fare qualsiasi altra cosa.)

Tuttavia, il trasporto HTTP che funziona su uno script CGI (!) Non lo supporta.

+0

È ancora vero quando avvio il server nel mio codice con LocateRegistry.createRegistry() (invece di usare l'eseguibile fornito da Sun)? –

+0

+1 per "(E sì, RMI è un PITA da configurare e fare qualsiasi altra cosa con.)" Per favore, dillo alla mia scuola. – Luc

2

Consolidare tutte le risposte qui, ho implementato 2 vie RMI tra client e server con il server esponendo la sua stub utilizzando Registro

  1. Il cliente riceve uno stub del server dal registro RMI
  2. Quindi il client invia lo stub come Observer al metodo addObserver del server
  3. Il server notifica i client utilizzando questo stub

il seguente codice dà un'idea migliore

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

In base al codice, la classe RmiClient può essere utilizzata sul server quando la classe RmiServer implementa l'addObserver methed. La classe RmiClient è definita nel client e nel server? – KUN