2009-07-27 9 views
8

Mam klienta, który uruchamia długo działający proces na serwerze. W regularnych odstępach czasu chciałbym pokazać użytkownikowi, co dzieje się w tle. Najprostszym sposobem jest odpytanie serwera, ale zastanawiam się, czy nie było sposobu na zaimplementowanie wzorca Obserwatora. Niestety, używam RMI do rozmowy z serwerem i obawiam się, że muszę zamienić mojego klienta na serwer RMI.Jak zaimplementować wzorzec Obserwatora za pomocą Java RMI?

Czy istnieje inny sposób, którego mi brakuje?

+1

Próbuję to zrobić również i doszedłem do tego samego wniosku ... RMI trochę do bani! :) – JohnIdol

Odpowiedz

1

Nie sądzę, że czegoś brakuje. Jedynymi dwoma sposobami są okresowe wywoływanie serwera i sprawdzanie statusu (odpytywanie) lub rejestrowanie wywołania zwrotnego, które serwer okresowo wywołuje (klient musi ujawnić metodę). IMO, sondowanie jest całkowicie rozsądnym sposobem poradzenia sobie z tym.

3

RMI może ogólnie wspierać dwukierunkową komunikację. (I tak, RMI to PITA, aby skonfigurować i zrobić cokolwiek innego z.)

Jednak transport HTTP, który działa na skrypcie CGI (!), Nie obsługuje go.

+0

Czy to nadal prawda, gdy uruchamiam serwer w moim kodzie za pomocą LocateRegistry.createRegistry() (zamiast używania pliku wykonywalnego dostarczonego przez Sun)? –

+0

+1 dla "(I tak, RMI to PITA do konfiguracji i robienia czegokolwiek innego.)" Proszę powiedz mojej szkole. – Luc

2

Konsolidacja wszystkie odpowiedzi tutaj, I wdrożone 2 drożny RMI między klientem a serwerem z serwerem wystawiając swój niedopałek za pomocą rejestru

  1. Klient dostaje niedopałek serwera z rejestru RMI
  2. Następnie klient umieszcza swój kod pośredniczący jako obserwator w serwerze metody addObserver.
  3. Serwer powiadamia klientów korzystających z tego kodu pośredniczącego

Poniższy kod daje lepszy pomysł

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

Bazując na kodzie, klasa RmiClient może być użyta na serwerze, gdy klasa RmiServer zaimplementuje proces dodawania usługi addObserver. Czy jest to klasa RmiClient zdefiniowana zarówno w kliencie, jak i na serwerze? – KUN