Mary
Mary

Reputation: 572

Java single threaded RMI or alternative

The Lotus Notes Java library only runs in 32-bit JVM, and I need to call it from my 64-bit JVM app, so I wrote an RMI bridge: The 64-bit app runs the 32-bit RMI server, and talks to the 32-bit server to make Lotus Notes calls.

Lotus Notes requires each thread (that will call any Lotus Notes functions) to call lotus.domino.NotesThread.sinitThread(); before calling any other Lotus Notes functions, and to cleanup at the very end by calling the un-init function, and these calls can be expensive.

Since RMI does not guarantee single-threaded execution, how can I pipe all the requests to a a single thread that has been initialized for Lotus Notes? I'm open to other RPC/"bridge" methods as well (prefer to use Java). Currently, I would have to make sure EVERY RMI function call I have defined makes sure its thread is initialized.

Upvotes: 1

Views: 571

Answers (2)

Mary
Mary

Reputation: 572

getName() is a simple example, so each code gets this kind of treatment (which bloats the code tremendously, but it works!)

    @Override
    public String getName() throws RemoteException, NotesException {
        java.util.concurrent.Callable<String> callableRoutine =
                new java.util.concurrent.Callable<String>() {

                    @Override
                    public String call() throws java.rmi.RemoteException, NotesException {
                        return lnView.getName();
                    }
                };
        try {
            return executor.submit(callableRoutine).get();
        } catch (Exception ex) {
            handleExceptions(ex);
            return null; // not used
        }
    }


/**
 * Handle exceptions from serializing to a thread.
 *
 * This routine always throws an exception, does not return normally.
 *
 * @param ex
 * @throws java.rmi.RemoteException
 * @throws NotesException
 */
private void handleExceptions(Throwable ex) throws java.rmi.RemoteException, NotesException {
    if (ex instanceof ExecutionException) {
        Throwable t = ex.getCause();
        if (t instanceof java.rmi.RemoteException) {
            throw (java.rmi.RemoteException) ex.getCause();
        } else if (t instanceof NotesException) {
            throw (NotesException) ex.getCause();
        } else {
            throw new NotesException(LnRemote.lnErrorRmi, utMisc.getExceptionMessageClean(t), t);
        }
    } else {
        throw new NotesException(LnRemote.lnErrorRmi, utMisc.getExceptionMessageClean(ex), ex);
    }
}

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691755

Use a single thread executor service, and each time you want to call a lotus notes method, submit a task to the executor, get the returned Future, and get the result of the method call from the Future.

For example, to call the method Bar getFoo(), you would use the following code:

Callable<Bar> getFoo = new Callable<Bar>() {
    @Override
    public Bar call() {
        return lotuNotes.getFoo();
    }
};
Future<Bar> future = executor.submit(getFoo);
return future.get();

Upvotes: 1

Related Questions