Reputation: 572
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
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
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