I'm developing a application using Java RMI which enable clients to register topics they want to listen (zero or more) and topic (zero or one) they want to speak about. There is a central server which offers registration service. The communication of clients avoids server with the exception of initial registering of ListenerCallback or SpeakerCallback. Clients and server work according to Observer pattern.
Callback interfaces:
public interface ListenerCallback extends Remote{
void notify(String topic, String msg) throws RemoteException;
}
public interface SpeakerCallback extends Remote{
Unregister accept(ListenerCallback listenerCallback) throws RemoteException;
}
Fragment of registration method on server, both speaker and listener are remote references:
for (SpeakerCallback speaker : registeredSpeakers){
try {
speaker.accept(listener);
} catch (RemoteException e){
//TODO should I unregister speaker?
}
}
As written above in //TODO, I suppose I should unregister speaker from my application registries, because as far as I know RemoteException indicates that the connection with client is broken.
The problem I'm struggling with is how should I manage abnormal client shutdown that only listen to some topic but speak about none. The server holds them in application registries, but has no way to determine whether they are still valid, because it doesn't call its notify() method.
Shoud I add some bogus method to ListenerCallback interface just for trying to determine whether client is still reachable?
Or should I implemented a protocol which would enable clients who speak about (these call notify() method) a certain topic notify server that some listening clients are no more available?
This is a job for the Remote Session pattern. Every client does a login step, which allocates and returns a new remote object which is really a session object, which in turn:
has a logout()
method, which unexports the object
provides the other APIs the client needs, and
implements Unreferenced
, with the unreferenced()
method calling logout()
.
So if the client either calls logout()
or dies the object will disappear; and whatever collateral actions need to happen can all happen in the logout()
method.