Domino Upgrade

VersionSupport end
Upgrade to 9.x now!
(see the full Lotus lifcyle) To make your upgrade a success use the Upgrade Cheat Sheet.
Contemplating to replace Notes? You have to read this! (also available on Slideshare)


Other languages on request.


Useful Tools

Get Firefox
Use OpenDNS
The support for Windows XP has come to an end . Time to consider an alternative to move on.

About Me

I am the "IBM Collaboration & Productivity Advisor" for IBM Asia Pacific. I'm based in Singapore.
Reach out to me via:
Follow notessensei on Twitter
Amazon Store
Amazon Kindle
NotesSensei's Spreadshirt shop


Command line mail merge

As shown before mail merging with Notes and {{mustache}} is simple and easy to code. To be able to run merging on the command line, I modified the bean and removed the XPages dependency and added a static main function. Now you can run it off the command line easily. It requires 5 parameters:
  1. the database name
  2. the CSV file
  3. a file with a HTML message including {{mustache}} tags
  4. a file with a Text message including {{mustache}} tags
  5. The senders eMail

Read More


Mail Merge with XPages

Being able to have individualized letters based on a template was one of the drivers to make Word processors popular. In the age of mass-communication of one. This tasks falls no longer to the printer, but your eMail processor. For a complete solution, check out Chris Toohey's excellent Mailer application, that is yours for USD 5.00 only.
I was wondering what it would take to build something similar, minus the address management, in XPages. I defined a few constraints:
  • I don't want to store the address list or the raw message
  • I need to be able to send images
  • I need to be able to fine tune the HTML
  • No sending of attachments required
  • Message needs to be individual using parameters (in the Body only), list of parameters will be flexible supplied together with the eMails as CSV data
So I created the MergeManager Java bean. Along the way I made a few experiences:
  • When bound to a bean the XPages RichText control wants a data type of
  • The IBM Image upload doesn't work with a bean bound RichText control, but dragging and dropping works. I got rid of the button with a single line of code:
    config.removeButtons = 'IbmImage';
  • When adding the Dropdown for the variables, a simple change allowed me to show the View source button:
    {"name" : "mustache", "items" : ["mustache","Source"] });
  • I reused parts of Toni's eMail bean, which I stripped of the attachment function and added direct deposition into the Works like a charm
  • There are lots of loose ends to consider: using the OpenNTF Domino API to gain easy access to theads to send the messages in the background would be top on the list. Allow template storage, different messages for HTML and Text (and EE), eMail preview some of the others. But that's a story for another time
The result is a reusable bean for custom mass eMails.
Read More


Application Migration vs. XPage enablement

In a recent customer discussion a claim was made: "If Notes client application don't automagically can be converted into XPages applications, then we very well can migrate to another platform, it is just the same". An interesting claim, I'll subject it to a reality check. In any case it is a good idea to revisit your investment in your existing applications first.

XPages Enablement

Gradual availability of new functions
  • A reasonable estimate for the required effort is up to 30% of the initial effort. It very much depends on the quality of the existing applications and familiarity and skills of your team
  • There is no data migration, so existing users using a Notes client can continue to use the application until you retire the Notes clients
  • You can look at your application from a functionality and user perspective. A typical first XPages application is an approval module that spans across all your existing applications and provides a single view into anything that needs approval. A next level is forms and tools for mobile personell
  • Domino's security model works in XPages too, so no changes are required
  • If a function in an XPage shows a bug, it doesn't stop executing the function, since a user can fall back to a Notes client until the bug is fixed
  • Mail notifications just work, it's Domino. Also you can build Attention Central
So in a nutshell: low risk, incremental availability, no data migration, freedom to innovate
Read More


Poking around the iNotes HTTP API (Part 3) - retrieve message meta data

So far we learned about the URLs, how to retrieve the Outline that contains folders and views and how to utilize JavaScript to deal with an API tha hadn't been designed for language neutral access. This part will deal with the retrieval of messages. There are quite some formats, strategies and tweaks to consider:
  • A message consists of headers (fields), and message parts that can be plain text, HTML, embedded images, attachments or other stuff (like the JSON used for embedded experiences). When to retrieve what part is an excellent question
  • Depending on your use case, your final client might or might not have access to the original iNotes implementation (Firewall, Offline, VPN), so just showing the HTML and let it fetch missing pieces might not do the trick
  • The HTML retrieved might not be well formed or contain links you don't want to execute (tracker images, tracker CSS, JavaScript stuff)
  • Automatically retrieving the whole message can be network heavy if there are large images or attachments in the MIME parts, this needs to be planned carefully
  • iNotes allows to retrieve the message fields as (kind-of) JSON using l_JSVars or retrieve the MIME headers using l_MailMessageHeader
  • The content of the message is accessible via s_MailMemoReadBodyContent or UNID/Body?OpenField or l_MailMessageHeader&PresetFields=FullMessage;1 (as raw Mime)
  • The MIME parts retrieved come infested with <br /> tags, since iNotes renders them in a display window (I would have used <pre>, but that's a different story. So they need cleanup
To begin I'll use the result of l_JSVars to learn about the document. Since, again, it is JavaScript, not JSON, I'll take the Rhino approach to extract a Java object.
The parts I'm interested in is in the variable named DXX which contains item that is a representation of NotesItems. True to the nature of an item, the JSON is quite elaborate, which you can see on the example of the form item:
{ "@name": "Form",
  "textlist": {
    "text": [
        {"0": "Memo"}

For our purposes this will be flattened into a Map that has the item name as key. The Java code is quite similar to the retrieval of the Outline, the magic is in the JavaScript:
public MessageObject(String code, String rawMsg) {
    long start = System.currentTimeMillis();
    ScriptEngine engine = new ScriptEngineManager().getEngineByExtension("js");
    Invocable jsFunc = (Invocable) engine;
    MessageObject msg = (MessageObject) jsFunc.invokeFunction("getMessageObject", rawMsg);
    long end = System.currentTimeMillis();
    System.out.print("Time in ms:");
    return msg;

A little detail to stumble over is the item structure. It can be textlist/text or only text (feels like MIME Headers) and datetimelist/datetimepair/datetime or datetimelist/datetime.
Read More


Poking around the iNotes HTTP API (Part 2) - Fun with Rhino

The iNotes HTTP API wasn't designed for consumption outside the iNotes web client. This becomes apparent when looking at Form=l_GetOutline_JSON or Form=l_JSVars that return JavaScript and not JSON! The difference? JSON contains data only, while JavaScript contains function definitions too.
To make use of data included in the JavaScript there are 2 possibilities:
  • do some elaborate String operation
  • actually run JavaScript
Since Java 6, the JDK contains a JavaScript engine, that originally was developed as Mozilla Rhino. The most recent incarnation in Java 8 is Nashorn (which is German for Rhino). When you use an older JDK, think "older JS", nice functions like JSON.stringify or JSON.parse are missing and need to be added from elsewhere.
Turning the outline information into something Java useful we need to parse the returned JSON, lets see how that works. The Outline is a little more complex that it might seem. The JSON delivers 6 values (in an array) about the outline entries:
  1. The hierarchical sequence number. Something like 1 or 3.1 or 3.2.1 - depending on the level. The numbers have gaps where entries in the Outline are hidden from the web
  2. The hierarchy level starting with 0. So Asia\South-East\Singapore would be level 2
  3. The Label of the entry. Can be different from the actual name of the element
  4. The full path to the image for that entry. We'll strip that to get the name without a path, so we can use our own icons
  5. The full URL to that entry. It has the View Label (Name) and its UNID or system name in the string. We need the UNID for the unread count, so we'll extract that
  6. Can something be dragged there. 1 = Yes, it is a real folder, 0 = probably not, it is a view or a label only. "Probably" since e.g. you should be able to drag into the "Delete" view

Read More


Poking around the iNotes HTTP API (Part 1)

With the rise of web applications, something interesting happened: applications gained an observable API. Delivered over HTTP(s) with a few commands (GET, POST etc.) it became easier to find out "what is going on". Tools like Wireshark, Fiddler, Charlesproxy or TCPMon sit between your HTTP consuming client and the HTTP generating server. In browser applications the build in developer tools (Ctrl-Shift-I) provide the same level of access.
So anything flowing over HTTP is effectively an API. This led to the idea of the API economy (but that's a story for another time). Intercepting HTTP(s) traffic can be easier and more fun, than trying to customise customise a backend you might not have access to. (Of course there is evil interception too). Point is case, iNotes is quite a stack:
3d view of the iNotes client

So I poked around the iNotes API, this is what I found:
Read More


Flashcards - German Version: Die Lernkartei

The offspring and SWMBO had an argument about the need for Chinese tuition when attending Singapore's oldest school. You can guess who had what position. Disecting the positions and looking at interest (you remember your basic negotiation skills, do you?) it boiled down to the wish of self directed learning vs. fear of failure.
Having gone through both (I remember my Latin tuition teacher well. I loathed him and in return he pushed me within 6 month from F to A), I concluded: self direction needs skills. So one task to complete is Learning how to learn. To be very clear: no technique can replace the I want to learn, but once the want is established, being skilful helps (and reinforces the want). Cousera even has a Learn how to learn class online.
One tool, well established for learning facts (like vocabulary), are flash cards (there are others). Interestingly the Germans put some rigor into the general idea of sets of flash cards using a Lernkartei. The Lernkartei uses a spaced repetition approach proposed as early as 1885 and made popular by Sebastian Leitner.
The Learnbox as proposed by Sebasitan Leitner
In a nutshell:
At stage 1 the learner adds new learning topics (vocables, phrases, facts) in bundles of 6-10 with up to 30 cards a day. These cards are reviewed and learned until they are memorised for the session. They then go into stage 2. When reviewing stage 2 cards, successful memorised cards go to stack 3 and failed cards back to stack 1. A successful review on stack 3 promotes the cards to stack 4, while a failure demotes it to stack 1. Stack 5 cards are considered retired and are archived after one successful review.
The key of the system is the ever increasing interval between the reviews: stage 1 is reviewed daily, stage 2 every 3 days, stage 3 every 5, stage 4 every 7 and stage 5 just occasionally. There are other interval suggestions available too.
You might have guessed: that system has been put into software, more than once. One popular application is Anki (which uses the SuperMemo algorithm). Others add a social component.
All application I glanced at made one basic assumption: there is one question with one answer (which might be reversible). However reality for vocabulary is a little more complex:
A word has more than one dimension
* only limited suitability as answer
So what to do? Write a multi-facetted flash card app? A flashy diamond perhaps?
Read More


Last usage of a mail file - for all users

My admin is getting a little rusty. When I was asked: "How can I indentify a dormant mailbox?" I couldn't name a place in admin where to look. Of course, there is the NotesDatabase.LastModified property, but that would get updated on a design refresh too. So I asked innocently: "dormant, how?" After an amusing 2 hour discussion between the stake holders (only the popcorn was missing) we concluded that it is either
  • No document has been created for a while (including incoming)
  • No email has been sent for a while
Calendar entries or todo were not part of the consideration, but that's just a question in what view you look. For "any" document it is ($All) and for sent documents ($Sent). The LotusScript code is just a few lines. I needs to be run, so it can access all mailboxes.
Read More


Providing user information in JSON

In the MUSE project we encountered the need to retrieve user information in JSON format. Easy done one would think. The trouble starts, when you have multiple directories and you need reasonable speed. Sometimes falling back to @Fomulas gives you what you need, fast and easy. @NameLookup knows where to look and you don't need any extra configuration. A simple call to an form will give you all you need: https://yourserver/somedb.nsf/namelookup?Readform for yourself or add &User=John Doe for any other user. This will return:
"QueryName": "John Doe",
"NotesName": "CN=John Doe/OU=ThePitt/O=GIJoe",
"AllNames": [
"CN=John Doe/OU=ThePitt/O=GIJoe",
"John Doe/ThePitt/GIJoe",
"John Doe",
"eMail": "",
"MailDomain": "SACMEA",
"MailServer": "CN=PittServer42/OU=ThePitt/O=GIJoe",
"MailFile": "mail/jdoe.NSF",
"Empnum": "0815",
"Empcc": "4711">

The form makes extensive use of @NameLookup and looks in DXL quite simple.
Read More


Building a shared approval frontend in XPages

The saying goes: "God would not have been able to create the world in 7 days, if there would have been an installed base to take care of". As much as we wish to have divine powers, we need to make with less and look after an installed base. Point in case: You have a set of approval applications in classic Notes client code, like: Travel, Leave, Expenses, Gifts, Training, BoM changes etc. You are challenged to provide a web and/or mobile interface for them.
Considering your options you have to decide between options:
  1. Dump the applications and rebuild them on a new platform. Hope that it will take long enough, so nobody will ask you to migrate any of the existing data
  2. Enable them one-by-one
  3. Hire Redpill to do an asymmetric modernization
  4. Build a lateral approval screen across your applications and leave the full web enablement for later
While #1 would allow you to silently dump all your technical debt, it will take too long and a potential data migration monster would lurk in the dark. #2 is what non-techies would expect, but again you spend too much time and you will carry forward new technical debt. After all the applications are more similar than different. Hiring Redpill would be a sensible option, but that requires board approval or is against your "we-do-it-inhouse" policy or you simply want to expand your skill horizon.
This leaves you with #4. To do this successful, you need to define your scope clearly. In the rest of the article I will work with the following assumptions, if they don't fit your situation, adjust your plan:
  • The goal is to provide the decision making screen only, not a complete workflow engine (it could evolve to that)
  • Request submission happens in the existing application, providing a new interface for that is outside the current scope
  • The flow logic (how many approvers per level etc.) is determined on submission by the original application
  • Someone from a different department indicated interest to use the approval screen from a complete different system (that is the "scope creep" that happens in any project)
When you look at workflow systems, while planning your application, you will notice, that there are 2 types of data: the flow state/sequence and the specific request data. The flow state is stuff like: what's the current status, what are the potential decisions (usually: Yes, No, More info please), who are the past, current, future approvers. The specific request data is stuff like: duration and type of leave, price of items to purchase, customer involved etc.
In your existing applications the two are stored together (and will stay like that), but you need to extract the flow data to your new approvalCentral application. On the back of a napkin you draw this sequence:
Your approval workflow
(Image created with JS Sequence Diagrams and postprocessed with InkScape)

The green part of the application exists, the first question is: how to design the submission. There are a number of options you could choose from:
  • Have the Approval Central application poll participating applications on schedule. That option is least efficient, but might be your only choice if you can't touch the existing apps at all (happens more often than you think, when admins are paranoid policies are set very cautious
  • Have each application create a flow document directly in the workflow central application. You could use a inherited LotusScript library for that. While that might have been the prefered choice a decade ago, it has two problems: first you limit your participating applications to Notes only (and there are other applications with decision requirements) and you would expose the inner workings of your application prematurely
  • Use a web service interface to implement Contract first development. While REST is the current IT fashion, you pick SOAP. The simple reason: LotusScript can talk SOAP quite well via the Webservice consumer design element, while REST would require your notification code being written in Java. So a SOAP service it is

Read More


This site is in no way affiliated, endorsed, sanctioned, supported, nor enlightened by Lotus Software nor IBM Corporation. I may be an employee, but the opinions, theories, facts, etc. presented here are my own and are in now way given in any official capacity. In short, these are my words and this is my site, not IBM's - and don't even begin to think otherwise. (Disclaimer shamelessly plugged from Rocky Oliver)
© 2003 - 2014 Stephan H. Wissel - some rights reserved as listed here: Creative Commons License
Unless otherwise labeled by its originating author, the content found on this site is made available under the terms of an Attribution/NonCommercial/ShareAlike Creative Commons License, with the exception that no rights are granted -- since they are not mine to grant -- in any logo, graphic design, trademarks or trade names of any type. Code samples and code downloads on this site are, unless otherwise labeled, made available under an Apache 2.0 license. Other license models are available on written request and written confirmation.