2009-07-27 26 views
8

Tengo un cliente que inicia un proceso de larga ejecución en el servidor. A intervalos regulares, me gustaría mostrarle al usuario lo que está sucediendo en el fondo. El enfoque más simple es sondear el servidor pero me pregunto si no hubo una forma de implementar el patrón Observer para esto. Desafortunadamente, estoy usando RMI para hablar con el servidor y me temo que tengo que convertir a mi cliente en un servidor RMI para esto.¿Cómo implementar el patrón Observer con Java RMI?

¿Hay alguna otra manera que me falta?

+1

que estoy tratando de hacer lo mismo y llegué a la misma conclusión ... RMI chupa un poco! :) – JohnIdol

Respuesta

1

No creo que te falte nada. Las únicas dos formas son llamar periódicamente al servidor y verificar el estado (sondeo) o registrar una devolución de llamada que el servidor llama periódicamente (su cliente debe exponer un método). OMI, el sondeo es una forma perfectamente razonable de manejar esto.

3

RMI puede en general admitir comunicación bidireccional. (Y sí, RMI es un PITA para configurar y hacer cualquier otra cosa con.)

Sin embargo, el transporte HTTP que funciona sobre un script CGI (!) No lo admite.

+0

¿Sigue siendo cierto cuando inicio el servidor en mi código con LocateRegistry.createRegistry() (en lugar de usar el ejecutable proporcionado por Sun)? –

+0

+1 por "(Y sí, RMI es un PITA para configurar y hacer cualquier otra cosa con)." Por favor, dígale a mi escuela eso. – Luc

2

la consolidación de todas las respuestas aquí, he implementado 2 vías RMI entre el cliente y el servidor con el servidor de exponer su talón de usar Registro

  1. El cliente obtiene un talón del servidor de registro RMI
  2. Luego el cliente coloca su stub como Observer en el método addObserver del servidor
  3. El servidor notifica a los clientes usando este stub

Lo siguiente código da una mejor idea

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

Basándose en su código, la clase RmiClient se puede usar en el servidor cuando la clase RmiServer implementa addObserver methed. ¿Es esa la clase RmiClient definida tanto en el cliente como en el servidor? – KUN

Cuestiones relacionadas