/** {@inheritDoc} */ public <V, T extends Throwable> V call(Callable<V, T> callable) throws IOException, T, InterruptedException { UserRequest<V, T> request = null; try { request = new UserRequest<V, T>(this, callable); UserResponse<V, T> r = request.call(this); return r.retrieve(this, UserRequest.getClassLoader(callable)); // re-wrap the exception so that we can capture the stack trace of the caller. } catch (ClassNotFoundException e) { IOException x = new IOException("Remote call on " + name + " failed"); x.initCause(e); throw x; } catch (Error e) { IOException x = new IOException("Remote call on " + name + " failed"); x.initCause(e); throw x; } finally { // since this is synchronous operation, when the round trip is over // we assume all the exported objects are out of scope. // (that is, the operation shouldn't spawn a new thread or altter // global state in the remote system. if (request != null) request.releaseExports(); } }