RMI Observer via RMI implementieren

Y

YXCFREWQA

Gast
Ich habe eine Konsolenanwendung, die Methoden via RMI zur verfügung stellt und eine GUI-Anwendung mit der ich über die RMI-Methoden Optionen setzen kann. Nun möchte ich einige Ausgaben aus der Konsolenanwendung in die GUI übertragen und die in der Konsolenanwendung vorhandene "Observable" anzapfen.
Ich kann mich verbinden und nun auch ohne Exceptions als Observer bei der Konsolenanwendunf eintragen, aber der Rückweg klappt leider nicht. Bei der GUI kommen keine Daten an.

Konsolenanwendung.
Java:
public class Console extends Observable implements RMI_Interface

  public Console(){
     UnicastRemoteObject.exportObject(this, 1099);
  }

  public void somethink(String s){
                  setChanged();
                  notifyObservers(s);
  }
}

public interface Console_RMI extends Remote {

  public void addObserver123(Observer observer, String s) throws RemoteException;

}

GUI-Anwendung (nur die Hilfsklassen für die Datenannahme)
Java:
public class RMI {

    private static RMI rmi = null;
    private static Console_RMI console;

    public static RMI getInstance() throws RemoteException, NotBoundException {
        if (rmi == null) {
            rmi = new RMI();
        }
        return rmi;
    }

    private RMI() throws RemoteException, NotBoundException {
    }

    public static boolean connect(String ip, int port) {
        boolean success = false;
        System.out.println("connect RMI with: " + ip + " " + port);
        Registry myRegistry;
        try {
            myRegistry = LocateRegistry.getRegistry(ip, port);
            console = (Console_RMI) myRegistry.lookup("console");
            success = true;

        } catch (NotBoundException ex) {
            Logger.getLogger(RMI.class.getName()).log(Level.SEVERE, null, ex);
        } catch (AccessException ex) {
            Logger.getLogger(RMI.class.getName()).log(Level.SEVERE, null, ex);
        } catch (RemoteException ex) {
            Logger.getLogger(RMI.class.getName()).log(Level.SEVERE, null, ex);
        }
        return success;

    }

    public Console_RMI getConsole() {
        return console;
    }
}





public class Helper implements Observer, Serializable {



    public Helper() throws RemoteException {
        try {
            RMI.getInstance().getConsole().addObserver123(this, "aaa");
        } catch (RemoteException ex) {
            Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NotBoundException ex) {
            Logger.getLogger(Helper.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("XXXXXXXXXXXXXXXXXXXX " + o + "    " + arg);

    }
}

Wo liegt mein (Denk-) Fehler? ;-)

Vielen Dank schonmal fürs Lesen!
 

Niki

Top Contributor
du willst dich mit deiner GUI Anwendung beim Server als Observer registrieren und dann vom Server über Änderungen z.bsp benachrichtigt werden? Dann brauchst du ein Callback Object am Server. Das heisst deine GUI Anwendung braucht ein Objekt, welches von UnicastRemoteObject ableitet und das du dem Server beim RMI Aufruf mit gibst. Der Server muss sich dieses Objekt merken und kann dann jederzeit Methoden darauf aufrufen, diese werden dann auf der GUI Anwendung aufgerufen.
 

Niki

Top Contributor
Hier ein kleines Demo Programm zum Veranschaulichen:

Java:
import java.rmi.Naming;

import rmi.server.ServerRemoteObject;

public class Client {

    public static void main(String[] args) {
        int port = 1099;

        try {
            ServerRemoteObject serverRemoteObject = (ServerRemoteObject) Naming.lookup("//localhost:" + port + "/"
                    + ServerRemoteObject.SERVICE_NAME);

            serverRemoteObject.addObserver(new RemoteObserverImpl());

            while (true) {
                Thread.sleep(1000);
                System.gc();
            }
        } catch (Exception e) {

            e.printStackTrace();
        }
    }
}

Java:
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import rmi.server.RemoteObserver;

public class RemoteObserverImpl extends UnicastRemoteObject implements RemoteObserver {

    private static final long serialVersionUID = 1L;

    protected RemoteObserverImpl() throws RemoteException {
        super();
    }

    public void update(Object o) {
        System.out.println("update received from server " + o);

    }
}

Java:
import java.util.ArrayList;
import java.util.List;

public class ObserverUpdater {
    private static final List<RemoteObserver> remoteObserverList = new ArrayList<RemoteObserver>();

    public static synchronized void addRemoteObserver(RemoteObserver observer) {
        remoteObserverList.add(observer);
    }

    public static synchronized void update(Object o) {
        List<RemoteObserver> brokenRemoteObserverList = new ArrayList<RemoteObserver>();
        for (RemoteObserver observer : remoteObserverList) {
            try {
                observer.update(o);
            } catch (Exception e) {
                System.err.println("observer disconnected, unsubscribing...");
                brokenRemoteObserverList.add(observer);
            }
        }
        remoteObserverList.removeAll(brokenRemoteObserverList);
    }
}

Java:
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteObserver extends Remote {
    void update(Object o) throws RemoteException;
}

Java:
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Server {

    public static void main(String[] args) {
        Registry registry = null;

        int port = 1099;
        try {
            registry = LocateRegistry.createRegistry(port);
        } catch (RemoteException e) {
            System.err.println("unable to create registry at port " + port);
        }

        if (registry == null) {
            try {
                registry = LocateRegistry.getRegistry(port);
            } catch (RemoteException e) {
                System.err.println("unable to get registry at port " + port);
            }
        }

        boolean ok = false;

        if (registry != null) {
            try {
                registry.rebind(ServerRemoteObject.SERVICE_NAME, new ServerRemoteObjectImpl());
                ok = true;
            } catch (Exception e) {
                System.err.println("unable to rebind object");
                e.printStackTrace();
            }
        }

        if (ok) {
            while (true) {

                String randomString = "" + ((int) (Math.random() * 100));
                System.out.println("updating clients with " + randomString);
                ObserverUpdater.update(randomString);
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                }
            }
        }
    }
}

Java:
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface ServerRemoteObject extends Remote {

    String SERVICE_NAME = "ServerRemoteObject";

    void addObserver(RemoteObserver remoteObserver) throws RemoteException;
}

Java:
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class ServerRemoteObjectImpl extends UnicastRemoteObject implements ServerRemoteObject {

    private static final long serialVersionUID = 1L;

    public ServerRemoteObjectImpl() throws RemoteException {
        super();
    }

    public void addObserver(RemoteObserver remoteObserver) throws RemoteException {
        ObserverUpdater.addRemoteObserver(remoteObserver);
    }

}

Einfach zuerst Server starten, dann Client starten. Der Server erzeugt alle 5 Sekunden eine Zufallszahl und schickt diese an alle Observer
 
T

tuxedo

Gast
Sofern du Callbacks nur im lokalen Netz verwendest, ist das echt eine feine Sache. Sobald du aber deine Anwendung über das Internet nutzt und somit Router und Firewalls dazwischen hast, wird's ganz schön hässlich. Den Grund kannst du hier nachlesen: RMI Callback Problem

Gruß
Alex
 

Ähnliche Java Themen

Neue Themen


Oben