Observer pattern over RMI
Jeg har et problem med observer over RMI.Jeg har lavet et eksempel hvor man starter serveren, binder serveren så den er tilgængelig for klienterne.
Når en client starter programmet, registrerer den sig på serveren for at modtage opdateringer om en liste over personer.
Mit problem er at når jeg via en client tilføjer en person på serveren, kaldes der en notifyAllClients() som kalder update() på de tilmeldte clienter, men den kan ikke kalde tilbage til mine registrerede objekter og kaster en exception.
Mit eksempel er lavet på baggrund af kap. 24 i bogen: Java Network Programming (http://www.manning.com/Hughes/)
Er der nogen der kan komme med en forklaring på problemet eller evt. komme med et alternativt løsningsforslag?
Her er min kode (Der er ozze en kode for Person, men den er der ikke noget specielt ved - Skriv hvis du gerne vil se den):
SERVERINTERFACE------------------------------------------------------------------------>
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import javax.swing.*;
public interface ServerIF extends Remote{
public abstract void deregister(Client client) throws RemoteException;
public abstract void addElement(PersonIF p) throws RemoteException;
public abstract DefaultComboBoxModel register(ClientIF client) throws RemoteException;
public abstract void createPerson(String n, int a) throws RemoteException;
public abstract void notifyClients() throws RemoteException;
}
SERVERIMPLEMENTERING---------------------------------------------------------------------->
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.*;
import javax.swing.*;
public class Server extends UnicastRemoteObject implements ServerIF{
protected DefaultComboBoxModel liste;
protected Vector clients;
public Server() throws RemoteException {
this.liste = new DefaultComboBoxModel();
this.clients = new Vector();
}
public synchronized void addElement(PersonIF p) throws RemoteException {
(this.liste).addElement(p);
this.notifyClients();
}
public synchronized void deregister(Client client) {
(this.clients).remove(client);
}
public static void main(String args[]) throws RemoteException, AlreadyBoundException {
try
{
System.out.println("Constructing server implementations...");
PersonIF p1 = new Person("Jesper", 10);
PersonIF p2 = new Person("Banke", 12);
ServerIF serv = new Server();
serv.addElement(p1);
serv.addElement(p2);
System.out.println("Starting up registry...!");
Registry registry = LocateRegistry.getRegistry();
System.out.println("Binding server implementations to registry...");
Naming.bind("jesper", p1);
Naming.bind("banke", p2);
registry.rebind("server", serv);
System.out.println("Waiting for invocations from clients...");
}
catch(Exception e)
{
System.out.println("Error: " + e);
}
}
public synchronized DefaultComboBoxModel register(ClientIF client) {
(this.clients).add(client);
return this.liste;
}
public void createPerson(String n, int a) throws RemoteException {
PersonIF pers = new Person(n, a);
this.addElement(pers);
}
public synchronized void notifyClients() throws RemoteException
{
for(int i = 0; i < (this.clients).size(); i++)
{
( (Client) (this.clients).elementAt(i) ).update(this.liste);
}
}
}
CLIENTINTERFACE------------------------------------------------------------------------------------>
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import javax.swing.*;
public interface ClientIF extends Remote {
public abstract void addElement(PersonIF p) throws RemoteException;
public abstract void update(DefaultComboBoxModel v) throws RemoteException;
}
CLIENTIMPLEMENTERING----------------------------------------------------------------------------------->
import javax.swing.*;
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.*;
public class Client extends UnicastRemoteObject implements ClientIF {
private DefaultComboBoxModel liste;
protected ServerIF server;
public Client() throws RemoteException, NotBoundException {
server = new Server();
liste = new DefaultComboBoxModel();
System.setSecurityManager(new RMISecurityManager());
String url = "10.40.2.70";
try
{
Registry registry = (Registry) LocateRegistry.getRegistry(url);//Naming.lookup("rmi://localhost/" + "registry");
server = (ServerIF) registry.lookup("server");
liste = server.register(this);
for(int i = 0; i < liste.getSize(); i++)
{
PersonIF tmp = (PersonIF) (liste.getElementAt(i));
System.out.println(tmp.getName());
}
GUI g;
g = new GUI(this);
}
catch(Exception e)
{
System.out.println("Error" + e);
}
}
public synchronized void addElement(PersonIF p) throws RemoteException {
server.addElement(p);
}
public DefaultComboBoxModel getListe() {
return this.liste;
}
public synchronized void update(DefaultComboBoxModel v) throws RemoteException {
this.liste = v;
}
public void createPerson(String n, int a) throws RemoteException {
(this.server).createPerson(n, a);
}
public static void main(String[] args) throws RemoteException, NotBoundException {
ClientIF client = new Client();
}
}
GUIIMPLEMENTERING-------------------------------------------------------------------------------------->
import javax.swing.*;
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
import java.util.*;
import java.awt.*;
import javax.swing.JFrame;
import java.awt.List;
import java.awt.event.*;
public class GUI extends JFrame implements ActionListener
{
private DefaultComboBoxModel liste;
private Client client;
private Button add, print, delete;
private JPanel conPanel;
public GUI(Client client)
{
this.client = client;
this.liste = client.getListe();
//Grænseflade-start
this.setSize (500,400);
this.setTitle ("Observer");
this.setVisible(true);
conPanel = new JPanel();
this.setContentPane(conPanel);
//Knapper:
add = new Button("Tilføj Person");
add.setBounds(300, 50, 85, 25);
print = new Button("Udskriv liste");
print.setBounds(300, 100, 85, 25);
delete = new Button("Slet Person");
delete.setBounds(300, 150, 85, 25);
//Tilføj ActionListeners
add.addActionListener (this);
print.addActionListener (this);
delete.addActionListener (this);
this.getContentPane().add(add);
this.getContentPane().add(print);
this.getContentPane().add(delete);
}
public void actionPerformed(ActionEvent ae)
{
try
{
if (ae.getSource ()== print {
for(int i = 0; i < (client.getListe()).getSize(); i++)
{
PersonIF tmp = (PersonIF) ((client.getListe()).getElementAt(i));
System.out.println(tmp.getName());
}
}
if (ae.getSource ()== add)
{
(this.client).createPerson("Knud", 21);
}
if (ae.getSource ()== delete)
{
}
}
catch (Exception e) {
System.out.println("Error: " + e);
}
}
public synchronized void addElement(ServerIF server, Person p) throws RemoteException {
(this.liste).addElement(p);
server.addElement(p);
}
public synchronized void update(DefaultComboBoxModel v) throws RemoteException
{
this.liste = v;
}
}