Bart van Heukelom
Bart van Heukelom

Reputation: 44114

Which RMI exceptions indicate lost connections

I'm using the following bit of code to notify remote (RMI) event listeners of a change.

        // notify remote listeners of this change
        ThreadPool.execute(new Runnable() { @Override public void run() {

            List<Integer> removal = new ArrayList<Integer>();

            listeners.getReadLock().lock();
            try {

                for (Entry<Integer, RemoteDataServerListener> e : listeners.entrySet()) {

                    try {
                        e.getValue().creditsChanged(player.getId(), player.getCredits());
                    } catch (RemoteException er) {

                        log.warn("Error in remote listener", er);

                        // this listener is gone
                        if (er instanceof NoSuchObjectException) {
                            log.info("Removing the listener");
                            removal.add(e.getKey());
                        }

                    }

                }

            } finally {
                listeners.getReadLock().unlock();
            }

            // listeners that are gone don't need future events
            listeners.removeAll(removal);


        }});

As you can see I remove a listener when it throws a NoSuchObjectException, but that's probably not the only exception that can be thrown. Is there a complete list of RMI exceptions that indicate a remote object (or entire server) is lost/disconnected?

Upvotes: 2

Views: 1503

Answers (3)

user207421
user207421

Reputation: 311039

That's a complicated question. Most of them don't indicate lost connections at all, in fact only UnmarshalException really does that, and only sometimes, e.g. when it wraps a ClassNotFoundException it doesn't indicate a lost connection.

In a sense ConnectIOException also indicates that, but it only happens when trying to revive a pooled client connection at the beginning of the call.

A more interesting and even more complex question is which exceptions preserve idempotence if you retry after them, and that is a very difficult question to answer. I devoted about 20 pages of my RMI book to that and I doubt that I covered every possibility.

NoSuchObjectException indicates that the remote object that exported the stub you are calling on is no longer there, i.e. has been unexported from its JVM.

RemoteException itself can mean practically anything, especially if you make the mistake of having your own application exceptions extend it. Don't do that. And in practice you shouldn't just catch RemoteException by itself, you should catch all the possible RMI exceptions separately with a catch-all RemoteException catcher at the bottom, as there are different recovery strategies for different exceptions. Unless you just want to give up on any remote error at all.

Upvotes: 1

Bart van Heukelom
Bart van Heukelom

Reputation: 44114

From http://download.oracle.com/javase/6/docs/api/java/rmi/RemoteException.html it looks like I can treat all RemoteExceptions that way, except:

  • UnmarshalException
  • UnexpectedException
  • ServerError

Upvotes: 0

Sanjay T. Sharma
Sanjay T. Sharma

Reputation: 23248

AFAIK, if you can ensure that your RMI application always throws back user defined or custom exceptions no matter what goes wrong at the server, catching RemoteException and removing the listener should be good to go. E.g.

public Object doSomething() throws RemoteException {
    Object o;
    try {
        // application processing
    } catch(final Throwable t) {
        throw new CustomException(t);
    }
    return o;
}

Upvotes: 0

Related Questions