Latest Updates

Products & Applications

Showtime
My Blackberry Enterprise Server Push Utility for the Lotus Notes Client, allows you to create Jobs for individual Channel, Message, and Browser Content Pushes, as well as allows you to delete Pushed Channel Icons from defined recipient devices.

Time Tracker
The idea is simple. At the start of your day - upon completion of your first task - create an entry highlighting what you did and whether you feel it was an efficient or inefficient use of your time. Based on several requests, you can also select the priority, apply categories, or even align your time against a project.

For Lotus Notes Client v8.0 and above, you can use the Time Tracker Widget to make this process even easier!

Zephyr
My Configuration-based Rich Text Mail Merge and Emailing Utility, Zephyr allows you to create rich, data-driven emails to support automated workflow - all via Microsoft Word Mail Merge-like architecture. Dear <firstname> allows you to personalize each email message not only to the individual recipient, but also to the individual application workflow event!

xCopy
xCopy is a simple configurable xCopy client for the Lotus Notes client. By creating and defining xCopy Profiles, you can batch process your file backup or remote upload jobs. With the addition of the xCopy sidebar widget, you can easily kick-off these jobs, and modify both the xCopy Profiles and xCopy itself.

Community & Resources

Lotus Technical Information & Education Community

The Lotus Technical Information & Education community is comprised of IBM, business partner, and customer subject matter experts who use product wikis, published articles, white papers, community blogs and the latest in social media to build and share high quality technical content.

OpenNTF.org - Open Source Community for Lotus Notes Domino

OpenNTF is devoted to enabling groups of individuals all over the world to collaborate on IBM Lotus Notes/Domino applications and release them as open source.

developerWorks Lotus : Wikis

Share your deployment experiences and best practices in our wikis and help IBM to create scenarios for successful deployments. Contribute to the community by collaborating on shared content and leverage the shared knowledge from that community.

Welcome to dominoGuru.com!

Focused on being the go-to resource for the IBM Lotus Notes Domino developer, dominoGuru.com delivers introductory-level best practices and advanced development deep dives for the IT professional, book and gadget reviews, and technical weblog, and more!

NotesDocument READ and UPDATE with AJAX calls to Domino Agents (or Simple Inline View Editing over the web) - Build, Demo, and Download

09/22/2009 10:30:03 AM by Chris Toohey

Building off of my example from yesterday, I thought that I would show you how we can quickly and easily create READ and UPDATE functions for NotesDocuments via calls to our (modified) HTTP Request Consumer Domino Agents. And, to spice things up, I thought I'd do it all via AJAX.

Build Synopsis

HTTP AJAX NotesDocument Mods Example NotesDatabase

That's the end-goal - a simple NotesData table that will allow us to change the Status of a given NotesDocument.

To get to that goal, I'll take the Agent Design Elements from yesterday - creating one for the READ and another for the UPDATE function. But first I need to ready the Page Design Element that acts as the Default Launch Object for the NotesDatabase, which will act as the display for our NotesData table.

Phase One: index.html Page Design Element

The index.html Page Design Element - just like with yesterday's example - is extremely simple by design: I want to focus your attention to the functional capabilities of having your Web Applications (Domino or non-Domino technologies-based) interacting with the HTTP Request Consumer Agents.

We'll focus on the HTML Form Element and the JavaScript functions, as the rest of the HTML markup is either descriptive/introduction or my Paypal Donation stuff.

The HTML Form Element contains the following markup:

<form action="#" name="moddocs" id="moddocs" method="GET">

<div id="viewbody"> </div>
<script>getdocs(document.getElementById("viewbody"));</script>

</form>

The JavaScript functions - there are two - are:

var http = false;

if(navigator.appName == "Microsoft Internet Explorer") {
http = new ActiveXObject("Microsoft.XMLHTTP");
} else {
http = new XMLHttpRequest();
}

function getdocs(target) {
http.open("GET", "getdocs.agent?open", true);
http.onreadystatechange=function() {
if(http.readyState == 4) {
target.innerHTML = http.responseText;
}
}
http.send(null);
}
function moddoc(val, UNID) {
http.open("GET", "status.agent?open&status=" + val + "&UNID=" + UNID, true);
http.onreadystatechange=function() {
if(http.readyState == 4) {
getdocs(document.getElementById("viewbody"));
}
}
http.send(null);
}

getdocs() simply grabs getdocs.agent Agent Design Element-generated markup and sets the innerHTML of the passed-thru HTML Object (via an AJAX call). moddoc() passes two values to the status.agent Agent Design Element: the new value of the status NotesItem and the target NotesDocument UNID (again, via AJAX). When it's complete, it runs another AJAX call to getdocs() to refresh the NotesData table.

All I need to do from here is make sure that my NotesData table has the markup it needs that wires into the moddoc(). Pretty simple, as via the getdocs() function I have absolute control over what's returned to the Web Browser Client.

Phase Two: HTTP Request Consumer Agents

The getdocs() and moddoc() simply require a modification to their respective Initialize subroutines to both deliver and update our NotesDocuments.

getdocs.agent Agent Design Element - Initialize

status.agent Agent Design Element - Initialize

... and that's it. The getdocs.agent Agent Design Element generates the markup that we need: the onchange event of each SELECT HTML Element passes the newly-selected value and the target NotesDocument Unique ID to the moddoc() JavaScript function, which calls our status.agent Agent Design Element. This processes the request - using the submitted UNID and status parameter values to find the target NotesDocument and update said NotesDocument status NotesItem respectively.

After that, we simply "refresh" the UI via another AJAX call... and we're done.

Online Demo, Example Download, and Closing Remarks

Again, for those of you who prefer an online demo complete with downloadable example, I've got you covered.

The code written in this series is - how should I put this - not ideal. In a "best practices" scenario here, you'd want to return something like JSON, and parse that JSON return locally. This code is about as simplified and straight forward as it gets - I didn't do anything that would subtract from the goal of this article: getting you to understand just what you can do with an HTTP Request Consumer Agent Design Element.

Hopefully, this is a simple enough showcase that you'll start delving into this practice yourself - regardless of your comfort level with LotusScript, JavaScript, HTML Method calls, and AJAX. It's really powerful stuff here, and your web applications will definitely benefit from the overall approach.

Notice I said web applications - which is the second time in this article that I haven't prefixed Domino as normal. I use this approach with Flash-based Banner Ads, simple HTML Forms hosted on IIS and Apache, and countless other scenarios. It's ultimately no different than using Google Web Services or any other SaaS or Cloud service. I take that back actually - using this approach, you can quickly and near-immediately bring Lotus Notes Client-only applications onto the Web and Mobile Browser Clients: simply point the target NotesDatabase to a different NotesDatabase, Domino Server, etc. and you have yourself a very powerful NotesData proxy on your hands...

When do you NOT help?

05/18/2009 12:47:26 PM by Chris Toohey

Maybe it should be a Yellow Hatter?I was contacted the other day by someone who came across my website -- specifically my Disabling $KeepPrivate documents! article -- who was looking for a method to add a Readers-type NotesItem to selected emails in his mail NotesDatabase. The issue that he was running into, he explained, was that his company prohibited personal Agents (and I suspect that each user only has Manager access to their mail NotesDatabase).

After explaining the potential issues with doing this - from the obvious "you could potentially lock yourself out" to the potential legal and corporate policy implications - I found out that he was concerned about his "nosey" boss reading his email.

Now, while I want this person to know that there are capabilities within the Lotus Notes client that will allow them to gain a richer experience and can improve the way that they perform their day-to-day functions, I don't want to condone such actions by me telling him how to do this.

And therein lies an issue: where do you draw the line?

I like to consider myself - at times - a Lotus White Hatter, but one person's White Hat can be another's Black Hatter. And in this particular case, I think the actions - at best - would be considered black hat, if not actionable!

So, Constant Reader, have you run into a similar situation?

SOTU - Remote Console Command Utility v0.3

01/06/2009 01:17:55 PM by Chris Toohey

I was once asked why I would created a little application that would do nothing more than what could be done with a simple SmartIcon. When I created SOTU - my Remote Console Command utility, it's v0.1 release was a simple utility that - yes - was an extended version of what you could do with a simple SmartIcon. v0.2 gave you the option to configure a simple Sidebar Widget, and allow you to issue Remote Console Commands to your Domino servers with even greater ease. With SOTU v0.3, you won't even have to fire up your laptop!

Simply point your mobile device's WAP browser to sotu.nsf/mobile, and you will be presented with a simple WAP-enabled Form:

SOTU - Mobile/WAP UI Screen Capture: 1

From here, you can select the Server and enter a console command. Click the Issue Command button, which submits the request via POST to a simple Domino Agent which uses the SOTU Script Library and issues the remote console command.

SOTU - Mobile/WAP UI Screen Capture: 2

Once properly executed, the browser is redirected to sotu.nsf/mobile, and can quickly see the response (if any) from the Remote Console Command via a pseudo-embedded View at the bottom of the mobile Form.

SOTU - Remote Console Command Utility v0.3

Quick Tip: For you Blackberry users, you can use Showtime to create a simple Channel Push icon for your Admin team and quickly deploy this application just in time for Lotusphere!

Here's a quick icon set that I used for my team - both a standard and an updated icon, shown respectively:

SOTU v0.3 - Showtime Blackberry Icon - Standard SOTU v0.3 - Showtime Blackberry Icon - Updated

See how I tie things in (eventually)?!

Also, v0.3 has no error handling in the mobile.engine which handles the request... and for good reason. If you get an Agent Done response form the Agent... then something's broken, and it's more than likely a permissions issue with the Remote Console security stuff (which can be changed on the Server Document). The Remote Console Command will be issued by the server, so make sure you have everything from a security side setup or you'll likely see something like this on the server console/log:

SOTU v0.3 Remote Console Command Utility - Mobile Server Console security error

Project: Zephyr - IBM Lotus Notes/Domino Notifications Utility

02/21/2008 02:24:04 PM by Chris Toohey

Author's Note: I figure if I name these things, I'll get them out...

I've gotten a lot of feedback - most of it offline, are people reluctant to comment?! - regarding the example notifications utility that I mentioned when discussing MMM yesterday - so much so in fact that it warrants me creating a new project here. And this is where Project: Zephyr is born!

Here's a diagram of the basic architecture of Zephyr, which will be a super-user-defined notifications utility for IBM Lotus Notes/Domino, that I quickly threw together:

Project: Zephyr - Architecture Diagram

Here, a copy of a document from a defined source Notes Application is placed in Zephyr. A scheduled Agent will run against all newly added documents, and check to see if an email template for the given source Application matches based on a defined criteria. If there's a match, the Agent will run a mail-merge of the source document and the designated email template - the result creating an email in the server's mail.box!

Simple stuff, I know.

I'm still hammering out the logistics here, but I already have a few production copies of this same utility floating around a few customer locations so I both know that it's a solid and useful solution. Left out of the diagram is the logging and retention-logic of the source documents.

One of the outstanding questions is, however, "How do I distribute it?"...

Addressing Domino Web-based @DBLookup limitations with Rich-Text and Context Profiles

12/16/2007 12:42:09 PM by Chris Toohey

Author's Note: I was asked by a good friend for a solution to get around a problem that is probably more common than we may think: web-based comboboxes/select field-types requiring lookups to data in the application. This is, most of the time, done via runtime-@DBLookups. My good friend contacted me more due to the fact that, as this application has grown, he's running into the dreaded @DBLookup/32Kb limitations, and he's looking for a way to solve his problem while keeping an eye towards future database bloat usage.

Now, I'll take the time to discuss two approaches to solving this problem - as I see this as two issues, as well as use his real-world example as a grounds for showing the application of said solutions. And without futher ado...

Erskine has a problem. Actually, some would argue that he has two problems. He's got what should be a very simple web client-based Domino application that relies on the typical mock-relation categorization: secondary documents which are used to create linked-by-keyword categories for primary/main documents. The majority of us developers have done this time and time again, simple and good-enough solutions that get the job done and the given project off of your task list. The problem this architecture runs into, as anyone who has written large-usage applications can tell you: you either 1) get bulky, clunky (read: slow) load times as your combobox/select field-type needs to look up a view for it's keywords or - and more critical (and what spawned the need for this article) you start to run into @DBLookup limitations due to the sheer volume of data that you're returning.

Now, the ideal solution would be to replace the entire mechanism for said lookups - go with a more name-picker approach to selecting a keyword - but as we need to maintain the current application as well as the user expectation of it's functionality (read: users will run in fear from your boomstick-like AJAX-based namepickers and other widgets), we'll left with only a few options. Heck, only one really good option in my opinion, which is what we'll get to in this article.

First, let's recap the current application:

This articles 'Current Architecture' diagram

We have a simple Domino application, which uses a View element to store a collection of keywords for our primary documents via secondary documents. The primary document Form element does a runtime @DBLookup to a view to return a list of said keywords for usage.

Now, your typical developer will not generate their own markup in the view, such as this:

"<option value=\"" + datavalue + "\">" + datavalue + "</option>"

- but rather have a list of values in a given column and let Domino generate the option element markup for them. So, before you get any smart ideas, you can't bypass this immediate need of addressing the @DBLookup error by simply pruning the markup...

Author's Note: Also, something to consider, feeding a combobox element a list of values and expecting Domino to generate your content will result in malformed and difficult-to-work-with markup. For example, simply supplying a list of values (val1:val2:val3) renders the option element without a value attribute - making interaction via JavaScript a much more difficult ordeal...

What we need here is a solution that will allow us to create a bunch of usable markup in a way that we 1) don't have to worry about nasty lookup limitations and 2) we improve the performance of the current runtime-based lookup facility. To achieve this, we'll take a look at an earlier publishing where we used the ability to control a document's Content Type to provide us with some quick-and-easily-maintained functional content, and we'll use this methodology as the cornerstone of our solution.

This articles 'Theorized Architecture' diagram

For this new architecure, we will need the following:

  1. Form: JavaScript Library Document|jslibrary
    1. Field: content - Rich Text.
    2. Content Type Form Attribute: text/javascript
  2. Agent: Summary|summary
    1. We'll want to loop through all of the Secondary Documents to gather our Primary Document keywords. Once we've gathered our volumous list, we'll format them for JavaScript usage (more details in the example)
    2. Schedule this whenever you need to really, it'll run in the back-end and be used to generate our JavaScript Library Document

We write a simple scheduled agent, Summary, to query the Domino application for all of our secondary document keyword data. Once that list is gathered and the javascript generated and formatted, we create a new document using the JavaScript Library Document form, which will contain nothing more really than a Rich Text field, which is where we'll store our JavaScript. The JavaScript Library Document form will have it's Content Type set to text/javascript. Now, when the newly-created JavaScript Library Document form-based doucment loads, the JavaScript will trigger and update the combobox/select field-type with all of our secondary document-maintained keywords without having to worry about any silly @DBLookup limitations or resource-intensive runtime routines.

That's it really - except for the example which should tie all of this together (I hope). The only thing that you should need now is the syntax for our JavaScript - that we will use to first clear the combobox/select field-type options and then add our own - and the particulars on how to generate that JavaScript markup. Other than that, it's a matter of getting a download ready (which will follow the publication of this article) and you should be good to go!