[java] event model met RMI

Pagina: 1
Acties:

  • Swinnio
  • Registratie: Maart 2001
  • Laatst online: 13:36
Ben bezig met een client-server programma, die via TCP communiceren en beide met behulp van j2se communiceren moeten. Vandaar dat ik voor RMI gekozen heb.
Het enige dat daarbij nog niet duidelijk is, is hoe je m.b.v. RMI een eenvoudig event model kunt opzetten. Dus: 1 of meerdere client registreren event listener bij server, die later de bijbehorende events aan elke geregistreerde client stuurt.
Er schijnen verschillende mogelijkheden te zijn:
* Dit artikel doet een voorstel, maar mede doordat alle sourcecode ontbreekt en het geen simpel voorbeeld is, krijg ik dit niet aan de gang.
* Jini schijnt een optie te zijn (zie onder andere dit artikel. Ziet er op zich goed uit, maar ik vraag me af of het nodig is jini hiervoor te gebruiken.
* Een simpele oplossing zou kunnen zijn van Observable class en Observer interface gebruik te maken, zoals hier
wordt voorgesteld. Een concrete toepassing of voorbeeld heb ik niet kunnen vinden.

De vraag is dus: wat is eenvoudigste oplossing events m.b.v. RMI te implementeren?

If the world wouldn't suck, we'd all fall off


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Hoe zou je het realiseren zonder RMI? :) Probeer dat eerst eens te doen.. het remote maken van deze aanpak is in essentie geen enkel probleem (er zijn wel wat belangrijke randproblemen waar je uiteindelijk ook rekening mee moet houden zoals het doodgaan van clients). Maar probeer het eerst eens te doen zonder rekening te houden met RMI. Als je wilt kan ik je daarna wel op pad helpen met de RMI toevoeging.

  • Swinnio
  • Registratie: Maart 2001
  • Laatst online: 13:36
Zonder RMI zou ik het realiseren zoals ik het altijd doe :)
Maar ik wilde in eerste instantie weten of het überhaupt zonder speciale trucs zoals jini mogelijk is. Als dat het geval is, ga ik er eerst wel mee aan de slag inderdaad....

If the world wouldn't suck, we'd all fall off


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Swinnio schreef op woensdag 20 juli 2005 @ 16:29:
Zonder RMI zou ik het realiseren zoals ik het altijd doe :)
Mooi zo...

Je moet niet vergeten dat je bij een interface (De observer) allerlei implementaties kunt maken :) Je zou dus gerust een implementatie die een callback doet over een remote interface naar de client toe (dit heet ook wel een proxy). Vanuit de observable is iedereen een observer.

[ Voor 3% gewijzigd door Alarmnummer op 20-07-2005 16:46 ]


  • Swinnio
  • Registratie: Maart 2001
  • Laatst online: 13:36
Wat mij in eerste instantie niet direct duidelijk was (is), is of de client in dat geval de rol van server overneemt. M.a.w.: de client-klasse die de callback ontvangt, is ook een remote object en het event op zich een remote interface.
Maar zoals gezegd, ik ga er eerst wel even mee aan de slag. Ben nog niet verder gekomen dan het voorbeeld dat gebruikt wordt in het boek Advanced Java (moet nog ff kijken of het voorbeeld ook ergens online te vinden is).

If the world wouldn't suck, we'd all fall off


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Swinnio schreef op woensdag 20 juli 2005 @ 19:00:
Wat mij in eerste instantie niet direct duidelijk was (is), is of de client in dat geval de rol van server overneemt. M.a.w.: de client-klasse die de callback ontvangt, is ook een remote object en het event op zich een remote interface.
Precies :) Door de callback speelt de client ook de rol als 'server'. Ik denk dat je het concept van client/server in dit geval een beetje moet laten varen. Zie het als een remote interface..

[ Voor 21% gewijzigd door Alarmnummer op 20-07-2005 19:24 ]


  • Swinnio
  • Registratie: Maart 2001
  • Laatst online: 13:36
Ok, het is me nu gelukt clients zich als listener te laten registreren bij een Remote Object. Het daadwerkelijk versturen van een event is echter nog een probleem: normaal gesproken heeft de event producer een WeakHashMap o.i.d. waar hij de listeners in registreert. Bij een event gaat hij d.m.v. een iterator alle listeners af en "verstuurt" het event m.b.v. een callback.
Maar nu zijn de listeners ook remote objects, die m.b.v. Naming.lookup gevonden moeten worden.
Hoe gaat dit nu samen?

If the world wouldn't suck, we'd all fall off


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Swinnio schreef op donderdag 21 juli 2005 @ 10:10:
Ok, het is me nu gelukt clients zich als listener te laten registreren bij een Remote Object. Het daadwerkelijk versturen van een event is echter nog een probleem: normaal gesproken heeft de event producer een WeakHashMap o.i.d. waar hij de listeners in registreert. Bij een event gaat hij d.m.v. een iterator alle listeners af en "verstuurt" het event m.b.v. een callback.
Maar nu zijn de listeners ook remote objects
Dat klopt.
, die m.b.v. Naming.lookup gevonden moeten worden.
Hoe gaat dit nu samen?
Ze hoeven niet via Naming gevonden te worden. Jij laat een client zich registeren als listener bij de server. De client moet een remote interface aan de server geven onder het mom: doe hier maar een call op om me dat event door te geven. Alle clients staan dus al in die WeakHashMap.

Dus de procuder zou moeten zeggen:

code:
1
2
3
4
Event bla = ..;
for(Listener l: listenerMap.values()){
     l.sendEvent(bla);
}


Dat zou voldoende moeten zijn.

  • Swinnio
  • Registratie: Maart 2001
  • Laatst online: 13:36
Het registeren van de listeners in de WeakHashMap lijkt niet helemaal goed te gaan. De event producer voegt een listener toe, maar wanneer later een event optreedt, is de hashmap leeg, hoewel de client er nog steeds is.

Op de console komt:
code:
1
2
Adding listener
Preparing events for 0 listeners


Op het moment van het event is de referentie naar de geregistreerde listener blijkbaar weg en de listener zelf dus uit de WeakHashMap verwijderd.

De event producer:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class EventProducerImpl extends UnicastRemoteObject implements
        EventProducer {
    private WeakHashMap listeners = new WeakHashMap();

    public EventProducerImpl() throws RemoteException {
        super();
    }
    
    public void addEventListener(EventListener listener) throws RemoteException {
        System.out.println("Adding listener");

        this.listeners.put(listener, new Integer(listener.hashCode()));
    }
   
    public void removeEventListener(EventListener listener)
            throws RemoteException {
        System.out.println("Removing listener");
        
        this.listeners.remove(listener);
    }

    public void fireEvent() {
        System.out.println("Preparing events for " + listeners.size()
                + " listeners");

        for (final Iterator iter = this.listeners.keySet().iterator(); iter
                .hasNext();) {
            final EventListener listener = (EventListener) iter.next();

            System.out.println("Firing event to listeners");

            try {
                listener.incomingEvent();
            } catch (RemoteException ex) {
                System.out
                        .println("RemoteException while sending event to client");
                ex.printStackTrace();
            }
        }
    }
}

[ Voor 11% gewijzigd door Swinnio op 21-07-2005 11:56 ]

If the world wouldn't suck, we'd all fall off


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Swinnio schreef op donderdag 21 juli 2005 @ 11:40:
Het registeren van de listeners in de WeakHashMap lijkt niet helemaal goed te gaan. De event producer voegt een listener toe, maar wanneer later een event optreedt, is de hashmap leeg, hoewel de client er nog steeds is.
Als niemand een referentie naar het object heeft, dan is het voor een weakhashmap niet voldoende om nog een referentie naar dat object vast te houden ;)

Wat je imho beter kunt doen is een heartbeat functie maken (dit doe je bij serieuzere systemen en gaat misschien te ver voor kleine dingetjes) waarmee je kunt controleren of clients nog leven. Dus een client kan zichzelf uitloggen, of de heart beat functie zal bij een dooie client de client uitloggen.

[edit]
En je stop eht in de verkeerde volgorde in die hashmap ;) Eerst de key en dan de waarde.. check de signature.

[ Voor 8% gewijzigd door Alarmnummer op 21-07-2005 12:44 ]


  • Swinnio
  • Registratie: Maart 2001
  • Laatst online: 13:36
Alarmnummer schreef op donderdag 21 juli 2005 @ 12:40:
[...]

Als niemand een referentie naar het object heeft, dan is het voor een weakhashmap niet voldoende om nog een referentie naar dat object vast te houden ;)

Wat je imho beter kunt doen is een heartbeat functie maken (dit doe je bij serieuzere systemen en gaat misschien te ver voor kleine dingetjes) waarmee je kunt controleren of clients nog leven. Dus een client kan zichzelf uitloggen, of de heart beat functie zal bij een dooie client de client uitloggen.
Ja, was al bang dat de WeakHashMap te weak was ;)
Van de andere kant: zowel het aantal clients als het aantal connects/disconnects zal waarschijnlijk zo gering zijn, dat een heartbeat functie inderdaad overkill zou zijn. Blijft de vraag: hoe dan de listeners op te slaan en te controleren of ze er nog zijn??

/edit: met een ArrayList gaat het vooralsnog goed (hoewel die natuurlijk niet kan controleren of clients nog leven). Volgende probleem is dat er een AccessControlException optreedt bij de callback... Neem aan dat dat komt doordat de server nog geen SecurityManager heeft en geen policy file gebruikt.

[ Voor 16% gewijzigd door Swinnio op 21-07-2005 13:10 ]

If the world wouldn't suck, we'd all fall off

Pagina: 1