I don't think there is a clean way of doing this in RMI given RMI doesn't offer an appropriate level of "socket" abstraction for this sort of stuff. Your best bet would be to pass a " callback handler " when "registering" or "joining" the chat. When the server wants to kick a client, it will just use the callback handler for that client (maybe stored in a Map at the server, name -> callback handler pair) to invoke the "kick" method. This kick() method will then be called in the "client JVM". In that method, you can "NULL" out the reference for the chat server.
Your client now no longer has the reference to the server and will have to make another call to "join" the chat. Just make sure you also call System.gc() and System.runFinalization() to ensure that the distributed garbage collector (DGC) kicks in and performs the necessary cleanup.
Some sample code:
public interface CommandHandler extends Remote {
void kick() throws RemoteException;
}
public class CommandHandlerImpl extends UnicastremoteObject implements CommandHandler {
private final Client client;
public CommandHandlerImpl(Client client) {
this.client = client;
}
public void kick() throws RemoteException {
this.client.chatService = null;
System.gc();
System.runFinalization();
System.out.println("You were kicked from the server, please reconnect!");
// update UI by clearing out all text boxes, list boxes etc. so that the user gets
// the impression that he was "actually" kicked out.
}
}
// Your main application class which has the chat server reference and does all the UI stuff
public class Client extends JFrame {
// remote service interface, the one which you lookup
private volatile ChatService chatService = null;
public static void main(final String[] args) {
final Client client = new Client();
client.init(); // look up chat server reference
// all the methods which use chat server reference must first check
// whether it is non-null. If it's NULL, it means that either this
// is the first time the client is connecting to the server or the
// client was forcefully kicked from the server (we can easily distinguish)
// by setting a flag when "kick()" is called.
}
}