Using Java to Create Rich GUI Interfaces in the Notes Client
This last couple of weeks I've made what I hope to be a brief return to developing for the Notes client. One of the requirements I had was to "add a form" to an existing Notes database, which allowed the user to input a few parameters and do a simple search of a remote SQL database, present the results to the user for their review before letting them import the resulting data in to the Notes database.
It goes without saying that I'd forgotten how to program in the Notes client. Having had such a long absence from Notes I came at it assuming that I could use Java code in the client (maybe you can and I missed something?).
For example, I'd assumed that, by now, I'd be able to write Java code in the Click event of a Button. As you can see below, this isn't an option.
I'm sure there's good reasons why we can't (is there?) but it left me a bit stuck. Was LotusScript my only option? I didn't relish the idea of fudging my way through getting LotusScript to do what I needed to do. It's not that I don't think it could. I'm sure it can, but it was a problem that really needed Java as the solution.
Not wanting to learn client development all over again or struggle trying to get LotusScript to do it I opted to write a Java Swing-based interface.
You can see an example below:
In the above example the user has clicked the Action button on the view and up popped the interface you can see. After entering some data and clicking a button the results table is populated from the SQL data. Then, when the Import button is pressed the data is saved in Notes -- a new document for each row of the table.
How does it work?
It's quite simple. The View's Action button looks like this:
This runs a Java Agent called "Import". Inside this agent the Java code simply creates an instance of a JFrame, adds all the components to it and then displays it. As far as the user's concerned it's just a part of Notes - when in fact it's a "standalone" Java application running inside Notes' JVM.
Powerful
The more I got in to this approach the more powerful I realised it was. Not only because the Java code is all self-contained in an Agent; meaning there are no installers or separate executable files to mange or distribute. But also because the app gets updated at the same time as the database design. Even the icons used in the buttons are stored as Resource files in the Agent itself. It's win win.
And because it's written in pure Java it's uses true OO patterns and a rich GUI. There are endless possibilities and pretty much no limit as to what you can do inside that popup window. I even managed to use a Thread to add and update a progress bar during the import process, which made me feel all geeky going multi-threaded (easier than it may sound!).
It also used a Data Access Layer (DAL) and data-modelling classes to abstract away from the SQL database. I had to do this as it's schema is subject to change. Also, at some point, the system will be moved off of Notes. At that point it will be easier to migrate this pure OO Java-based solution than it would be a Notes one.
It's worth noting that it runs inside the Notes JVM as the current user, meaning there's no need to store or ask for their password.
Gotchas
The one thing I don't like about using these Java windows is there's no way to open them as modal to the Notes client. It's all to easy for them to slip under the Notes client and the user to lose track of where it's gone.
However, they can be made to run (and stay) on top of all other windows, but that's a bit annoying. To do that would involve editing the java.policy file (found in <Notes Folder>\JVM\lib\security) on the user's machine and adding this permission:
permission java.awt.AWTPermission "setWindowAlwaysOnTop";
Then in the code itself you can set the Swing frame to stay on top, like so:
try{ frame.setAlwaysOnTop(true); } catch (SecurityException sex){ }
Also, I've I've yet to work out how to limit it to only showing one window at a time. If the windows pops below others and the user presses the View Action button again they end up with two of them. I'd rather it brought the first back in to focus.
The other gotcha I found was that any button click (or other event) handlers in the popup window had no access to the Agent's Session object. That's because the Agent itself has completed running and all the session-based object have been recycled. If you want the Java code to interact with Notes then you need to create a new session.
To do this I wrote the basis of the Agent like this:
public class JavaAgent extends AgentBase { private static String databaseServer; private static String databasePath; public void NotesMain() { try { Session session = getSession(); //So that later any session/threads can access this database databaseServer = session.getCurrentDatabase().getServer(); databasePath = session.getCurrentDatabase().getFilePath(); //Launch the dialog/form for user input //initializeUI(); } catch(Exception e) { e.printStackTrace(); } } private static void calledFromSwingUIAfterAgentIsDone(){ try{ NotesThread.sinitThread(); Session session = NotesFactory.createSession(); Database db = session.getDatabase(databaseServer, databasePath); Document doc = dc.createDocument(); //etc } catch (Exception e){ //report error } finally { NotesThread.stermThread(); } } }
Note that I stored the database's server name and file path in two Strings that we can refer to later when we create our own Session object and re-open the database.
Summary
All in all it's an approach I'm happy with and it's got the job done. Some of you may think it's crazy overkill but, for me, it was the best (if not only) solution.
If there's any interest I can package up a downloadable example?
Jake,
Super stuff. Been talking with some of the yellow bubble guys on this VERY subject.
Bit of a topic within some of the yellow bubble...but you should have a look at RCP development within Notes. Basically you are extending the Eclipse environment to customise things like right click menu options, popups, sidebar, dialogs the whole interface.
You also have access to the Java / NOI objects and some Notes Java UI objects.
Allows you to customise Notes, Designer, Symphony, Sametime...
Some great UI building tools (see Bob Balfe - SWT drag and drop stuff). OpenNTF has loads of examples.
Pig to setup (but mikkel heisterberg has great docs on it). Threading is also a thing to watch (UI and "back end" operations) - again there are classes that make it easier for you.
The whole Java / Eclipse / XPages stuff is great (you knew I was going to start going there!).
The great thing is its Eclipse so it can "stand alone" or integrate with the client / designer etc - giving you a load of options. Also the plugin architecture means that from an "admin perspective" deployment can be done centrally to your clients - just requires a re-boot. Properties can also be pushed out to your app centrally.. (whcih can be reset / managed / overridden in your client properties box)
Anyway .... waffling. If you get a project that would benefit this I am sure you would produce some great stuff.
Looks like a very useful tool as it stands!
Reply
Hi Chris,
Interesting. I might look in to RCP development as I would really like something more integrated in Notes - to avoid the issue I mentioned where the window could get lost under the others.
However, I quite like how my approach means there's no install needed whatsoever and it feels to the user like a natural part of the database itself.
Glad you mentioned SWT. I forgot to mention that I'd originally designed the interface shown above using the drag-n-drop after installing the SWT tools in pure Eclipse
https://developers.google.com/web-toolkit/tools/gwtdesigner/index
All very cool stuff.
Reply
Show the rest of this thread
Did a quick Google to see what RCP was. For any others curious, see here: http://www.eclipse.org/articles/Article-RCP-1/tutorial1.html
Reply
Jake,
Have a look at Bob Balfes blog and also Mikkel Heisterberg. Some great stuff there.
Domino Designer wiki also has some downloadable examples that you pull into eclipse and play with (as well as documentation on the whole shebang).
Eclipse RCP Redwiki (or something similar) its called.
Reply
Also...vogella...
http://www.vogella.com/eclipse.html
Brilliant articles there on the RCP / SWT side
You being an android guy will like that stuff there as well!
Reply
One clever way to deal with java permissions is to have a snippet of LostusScript (which isn't subject to java security policy) that finds and edits the java policy file. You generally have to restart the client for it to take effect, but it's an option.
As for multiple windows, I know there's a way that you can put a reference to your original JFrame somewhere global, which then allows you to check whether it exists already before creating a new one. If it's there, you can just order it to go to the front of the screen.
Reply
Hi Brian,
Put the JFrame reference somewhere global? Inside the Agent's code you mean? It is already is global. But, as I understand it, when the user clicks the Action button again the Agent is running afresh and knows nothing of the objects created last time it ran. Is that not so?
Reply
It is possible to find the window that you have opened: http://stackoverflow.com/questions/9276871/share-a-gui-jframe-between-agent-calls
"You can use Window class and iterate through all created instances"
"public static Window[] getWindows() and"
"public static Frame[] getFrames()"
Reply
Brilliant. Thanks Jasper. I hadn't gotten as far as googling for the answer yet. I invoked the lazy Web instead :)
Reply
It seems I am not the only one who is still being asked about (rich) client development simply based on the fact that companies still run a lot of those applications and many of them are mission critical.
Unfortunately IBM's pockets in this area are quite empty but I do like your approach. Thank you for sharing.
Reply
Welcome back Champ, great stuff!
If you follow Mickels set of posts you should be able to follow how to implement this as a side bar plug-in which means it's always available to the user, and is pure java, with the added benefits of Notes Classes, session integration, modality, etc...
Thanks, cool post!
Reply
Please post a downloadable example.
Reply
It would be very nice if you post your downloadable example. It would be nice starter for my new project :-)
Reply
Just a quick question Jake, how did you get around the annoying wait that users get the FIRST time the click on your agent? We have written quite a bit of code in Java to add functionality that is missing in Notes - what bugs me (not the users funnily enough :o) is when they press the action button the need to wait for the JVM to start. Have you found a way around this (e.g. start the JVM in the background when Notes starts)?
Reply
Aha. I wondered why it took longer first time ;-)
It's not got as far as the user using it yet. Hoping they won't mind the wait. Doesn't seem unreasonably long to me.
Reply