Shutting down rmi server cleanly

java, rmi

Solution

Unexport with force = true doesn't abort calls in progress. In general it will let in-progress calls run to completion. Your `shutDownServer` method is almost correct in that it unregisters the remote reference and unexports it. What it does next doesn't work, though. First, it sleeps for one second. This keeps the call in progress and keeps the client waiting for a reply. Then the shutdown code exits the server JVM without returning from the remote call. This closes client's connection while it's still awaiting a reply. That's why the client gets the connection reset exception.

To shut down cleanly, unregister the remote object, unexport it with force = true (as you've done) and then simply return. This will send a reply to the client, letting its remote call complete, and it will then exit. Back on the server, after the last in-progress call has completed, if there are no other objects exported, and if there's nothing else keeping the JVM around (such as non-daemon threads) the JVM will exit. You need to let RMI finish up its server-side processing instead of calling `System.exit()`.

Problem

I am running in to some trouble when shutting down the server component and was hoping to get some help. My server code looks as follows, it has a method to shut down the server Server ``` private final String address = "127.0.0.1"; private Registry registry; private int port = 6789; public RmiServer() throws RemoteException { try { registry = LocateRegistry.createRegistry(port); registry.rebind("rmiServer", this); } catch (RemoteException e) { logger.error("Unable to start the server. Exiting the application.", e); System.exit(-1); } } public void shutDownServer() throws RemoteException { int succesful = 0; try { registry.unbind("rmiServer"); UnicastRemoteObject.unexportObject(this, true); Thread.sleep(1000); } catch (NotBoundException e) { logger.error("Error shutting down the server - could not unbind the registry", e); succesful = -1; } catch (InterruptedException e) { logger.info("Unable to sleep when shutting down the server", e); succesful = -1; } catch (AccessException e) { logger.info("Access Exception", e); succesful = -1; } catch (UnmarshalException e) { System.out.println(e.detail.getMessage()); logger.info("UnMarshall Exception", e); succesful = -1; } catch (RemoteException e) { System.out.println(e.detail.getMessage()); logger.info("Remote Exception", e); succesful = -1; } logger.info("server shut down gracefully"); System.exit(succesful); } ``` My client connects fine, no issues, so to shutdown i created a new application, copied the client code to connect and then call the close method on the server Shutdown public class Shutdown { ``` private String serverAddress = "127.0.0.1"; private String serverPort = "6789"; private ReceiveMessageInterface rmiServer; private Registry registry; public Shutdown(){ try { registry = LocateRegistry.getRegistry(serverAddress, (new Integer(serverPort)).intValue()); rmiServer = (ReceiveMessageInterface) (registry.lookup("rmiServer")); logger.info("Client started correctly"); rmiServer.shutDownServer(); System.exit(0); } catch (UnmarshalException e ){ logger.error("Unmarshall exception. Exiting application", e); System.exit(-1); } catch (RemoteException e) { logger.error("Remote object exception occured when connecting to server. Exiting application", e); System.exit(-1); } catch (NotBoundException e) { logger.error("Not Bound Exception occured when connecting to server. Exiting application", e); System.exit(-1); } } ``` No matter what i try i keep getting the following exception; ``` ERROR com.rmi.client.RMIClient - Unmarshall exception. Exiting application java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is: java.net.SocketException: Connection reset at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source) at sun.rmi.server.UnicastRef.invoke(Unknown Source) at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source) at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source) at $Proxy0.shutDownServer(Unknown Source) at com.rmi.shutdown.Shutdown.<init>(Shutdown.java:31) at com.rmi.shutdown.Shutdown.main(Shutdown.java:52) Caused by: java.net.SocketException: Connection reset at java.net.SocketInputStream.read(Unknown Source) at java.io.BufferedInputStream.fill(Unknown Source) at java.io.BufferedInputStream.read(Unknown Source) at java.io.DataInputStream.readByte(Unknown Source) ... 7 more ``` I belive this might be due to the fact that the client is not properly disconnected and just gets "cut off" but i am unsure how else to disconnect the server side? please can some one advise. thanks

Original source