Domino Java agents & GUIs 12 Oct, 2003

Background

I was recently perusing the Notes 6 forum over at the Lotus Developer Domain, as is my wont, and I came across a post entitled, Database access from another class - Java. Now, normally, I would never post a "complete solution" as I did with this thread, but it piqued my interest. It took me a little time in terms of coding, experimenting, and researching Java in Domino, so I thought I'd summarise what I learned in a wee article.

Domino & Java

Whilst I've tinkered a fair bit with Java, one thing I don't have much experience of is creating Java agents. The nearest I got to a Java agent "in production" was a simple implementation of part of the Trackback specification. I did this for fun, but found no further use for it, and let the code languish. So this post on the LDD gave me a chance to "flex my muscles": coding the trackback thing was all "back-end" — Java with no user interface to speak of — whereas this little thing required a front-end that would interact with the agent calling it.

The code & the problem

The original poster in the thread wanted to invoke a simple GUI from a Java agent, collect user input via this GUI, and then do stuff back in the agent. He was using Java because he had a dependency in his code in the form of the JavaMail API. The issue he was experiencing concerned the separation of code into two classes (the main Java agent plus a simple AWT-based class) in that the two weren't talking to each other.

My starting point was to take the code he had, dump it into a dummy database, and get cracking. I called the main agent "DomGUIJavaAgent" and the class it uses for the GUI, "DomGUI". The poster had complained that his code didn't work on two fronts. First, his ViewEntryCollection object came up with inconsistent entry counts. That was easily solved, in that his for loop wasn't properly constructed. The rest of it was harder though…

The problem was that the standard NotesMain method happily instantiated a Database object and all the rest, but couldn't seem to pass these objects over to the default constructor of the GUI class. This meant a lot of head-scratching for me, although I knew it just had to be related to scope. Clearly, the Session and AgentContext classes were key: if they "died" *, then any objects derived with their help weren't going to survive either. I pondered this, and tinkered with different ways of somehow creating "new" AgentContext/ Session objects in the GUI code: not good. Eventually, my sorry excuse for a brain had an epiphany: we're getting into threads!

* - the Domino Java classes and interfaces are "wrappers" around core C functionality in Notes. As such, standard Java garbage collection doesn't work. A good Java coder needs to explicitly "recycle" Document objects and so forth. I gather that the exceptions to this rule are AgentContext and Session. For the sake of brevity in the source code, all recycle calls have been omitted.

Yup, threads

I've always been a bit leery of threads. They're one of those things, along with bit-signing and inner classes, that I seem to have a bit of blind spot with (getting better though!). Now, as I looked more and more into the Domino Java implementation, I discovered that AgentBase, the base class for all Java agents, is a sub-class of the NotesThread class, which makes sense. So, returning to our code, how about running the second GUI object in its own thread? That should work. But we still need to keep the "trigger" — the AgentBase object — alive.

The key to this is getting one thread to "sleep" until the other one is done. So here's my implementation:

In the constructor for the GUI object, I pass through a reference to the Database object we're playing with. The key thing though, is that the method in the DomGUI class that uses this Database object fires off in its own thread and that the Java agent's NotesMain method waits for it. This waiting is accomplished by making the Java agent thread "sleep" for as long as a public boolean variable, belonging to DomGUI, is set to "false." Whilst the thread is alive DomGUI can happily work with the passed-through Database object. Only two things can change the "isClosed" variable to "true": once the relevant button has been pressed or when the window is closed by the user. Splendid.

And here's a snippet of the action listener method in the DomGUI class which manipulates "isClosed", the crucial public boolean which holds this all together (sendToAll() is a simple demo method, as you'll see in the full source):

The threads

If you look at the full source, you'll notice that a method in the DomGUI code (sendToAll()) initialises its own thread. This thread isn't terminated until the whole window is closed.

Summary

I hope this is useful to any beginning Java coders out there like me… it's the fruit of a fair bit of playing, testing, and actually reading the Domino Designer help… :-o. Hopefully, it will act as a good starting point for any Domino-based Java you need to write that requires a UI. I appreciate that this isn't the prettiest GUI, but it's really just to show what can be done… and it's also R5-compliant!

My thanks to Joseph Millar of Brightline Technology for making a really useful observation concerning thread termination which I took on board in this code. Additional comments from those more experienced than I are more than welcome!

Joe, I think Swing is the replacement lib for AWT… but I haven't been keeping up on Java GUI… I try to avoid it, myself.Jerry Carter#

In one of my projects I had used Java agents for report generating using FOP (FO-XML), it works good. I also try to integrate JReport Designer with Lotus Notes, but problem is that my workstation are very strong, but the clients workstation - ooh.
I think use of Java in Lotus Notes will be more productive, if IBM will extend Java support to programming events as: onClick, etc.Egor Margineanu#

Hi

I have just found a need to provide a search form for a database and thought that Swing would be an answer. Yes! I hit on the problem the agent finishes and leaves the form alive.

This article has put me on the right track and saved me from a lot f head scratching!

Thanks!

Paul

I wonder if instead of have the NotesMain thread 'poll' the JFrame thread as suggested in the article it might be better to make the Notesthread block until the JFrame completes…? - something to mull over.Paul Bowman#

Yes, this is a valuable insight into the quirks of connecting Notes and Java programming. I've been writing socketed programming between Notes and my own custom applications and found that spinning off threads from the Notes Agent has been a fairly random and mysterious process.

In the end I had to simplify to try and stabilise things and found that just putting the main Notes thread to sleep for a second allowed all my classes to do their work before being destroyed when the main application shut down, taking everything with it.