By now (I assume you read part 1, part 2 and part 3) we have a working AgentBase extension called EclipseAgentBase which is capable of detecting whether the code is running inside Notes/Domino (and hence use the AgentBase functionality supplied by IBM) or outside Notes/Domino. If running outside Notes/Domino we use some custom functionality to “bootstrap” the runtime environment.
In part 3 I showed how to return a Session object from the getSession() method and a PrintWriter from the getAgentOutput() method. The problem with the getSession() method is that the returned Session is unaware of the runtime environment and a call to getAgentContext() will return null which isn’t what we want. Since lotus.domino.Session is an interface we can simply create our own implementation to wrap the returned Session.
To do this we simply create a wrapper for our Session and return the wrapper. Having the wrapper implement the lotus.domino.Session interface makes the caller oblivious to the change (change from part 3 in bold):
public Session getSession() { try { if (this.pIsNotes) { return super.getSession(); } else { if (null == this.pSession) { this.pSession = new SessionWrapper(NotesFactory.createSession()); } return this.pSession; } } catch (NotesException e) { throw new RuntimeException("Unable to create session", e); } }
The declaration of the SessionWrapper class is as follows:
private class SessionWrapper implements Session { // declarations private Session pSession = null; public SessionWrapper(Session session) { this.pSession = session; } ... ... }
The only caveat is that we have to implement all the methods of the lotus.domino.Session interface (all 62 of them) which is quite tedious. But here Eclipse comes to the rescue. Once the class and the pSession member variable has been defined you can simply right click and select “Generate Delegate Methods” from the Source-submenu. This will make Eclipse generate stubs for all methods and make the actual call go to the pSession member variable.
In this way we only need to override the methods we atually need to. This is a big time saver.
Once we return a SessionWrapper object instead of the Session from NotesFactory.createSession() we can do what we need to in relation to the AgentContext. The only method I choose to override from the lotus.domino.Session interface is the getAgentContext() method. Again we are in luck since AgentContext is an interface so we can do this using an anonymous inner class (in bold):
public AgentContext getAgentContext() throws NotesException { return new AgentContext() { ... }; }
We have to implement the 16 methods of the AgentContext interface but we can simply use the “Override/Implement Methods” functionality to generate the stubs to save some time and typing. Once we have done this all the methods return either null or 0 which isn’t what we want. Instead delegate all method calls to callback-methods (starting with “callback”) in the top EclipseAgentBase class as shown below for the getCurrentAgent() method which delegates to the callbackGetCurrentAgent() method:
public abstract class EclipseAgentBase extends AgentBase { ... ... protected Agent callbackGetCurrentAgent() throws NotesException { return null; } private class SessionWrapper implements Session { // declarations private Session pSession = null; public SessionWrapper(Session session) { this.pSession = session; } public AgentContext getAgentContext() throws NotesException { return new AgentContext() { public Agent getCurrentAgent() throws NotesException { return callbackGetCurrentAgent(); } }; } ... ... } }
The result of using the callback and just returning null is presently the same but using the callback gives us a lot of functionality as you’ll see in the next and final part of the series.