Installing and Configuring IBM Domino 9 Social Edition on CentOS 6 Enterprise Linux

QuickImage Category IBM Domino CentOS Linux Admin Articles Technical Show-n-Tell Thursday

I realize it is been a while since I posted, I'm hoping this blast of content will make up for my absence.

Since the official release of IBM Notes and Domino 9.0 Social Edition a few weeks ago, I have been "chomping at the bit" wanting to release a set of instructions / videos on how to install it on a Linux machine.

During the beta program I had the opportunity to "play" with it quite a bit, and let me tell you this release is exceptionally good. It is also by far the easiest and most hassle-free version I have ever installed on a Linux machine -but there are still a few gotchas and watch-outs to be wary of.

I have written an instructional document entitled Installing and Configuring IBM Domino 9 Social Edition on CentOS 6 Enterprise Linux. I hope it helps alleviate some of the fear and confusion with regards to using Linux as your Domino server platform. The document is aimed at YellowHeads (having some experience with Domino installations on Windows) who are thinking about stepping into the world of Linux. The document is focused on 64 bit Linux, but calls out differences from 32 bit installations where necessary. Even though it is aimed specifically at CentOS 6, the instructions should work for any RHEL or Debian-based (with some changes to handle DEB vs. RPM) linux version -although I must point out that the only supported Linux distributions are RHEL 6 and SUSE 11.

I have also cut a series of 9 videos wherein I walk through the instructions step-by step and demonstrate how easy it really is to perform the installation. They are available on my YouTube channel, although I'm hoping I can talk David Leedy into including them on Notes In 9.

Hope this helps!



Expanding a Names List

QuickImage Category Show-n-Tell Thursday LotusScript

Here is an old helper function I've had laying about in my toolkit for a while. It gets the unique members of a list of names or groups. Anyway, here is the code:

' * function expandNamesList
' * @author: Devin S. Olson
' * @licence: Apache License, Version 2.0
' **/
Function expandNamesList
Gets the unique members for a list of names and groups.
Conditionally recurses to get all individual members of all sub-groups.

@param directory: Source Address Book database within which to search for groups.
@param source: String or Array of Strings containing the members to expand.

@return Variant: Array of Strings containing the expanded unique members of source. Empty String ("") on error.
Function expandNamesList(directory As NotesDatabase, source As Variant) As Variant
Dim extendedInfo As String
Dim result As Variant
On Error GoTo ErrorTrap

Const VIEWNAME = |($VIMGroups)|

Static cachedb As NotesDatabase
Static groupsview As NotesView
Static recursions As Integer

Dim nvent As NotesViewEntry
Dim group As NotesDocument
Dim nongroupnames List As String
Dim subgroupmembers List As Variant
Dim subgroupnongroupnames List As Variant

Dim workingset As Variant
Dim membername As String
Dim sourcetype As String
Dim tag As String
Dim idx As Integer
Dim isRecursive As Boolean

isRecursive = (GetThreadInfo(LIB_LSI_THREAD_PROC) = GetThreadInfo(LIB_LSI_THREAD_CALLPROC))
If isRecursive Then incValue recursions%, 1


sourcetype$ = TypeName(source)
extendedInfo$ = |Source Type: | & sourcetype$
Select Case sourcetype$
workingset = toArray(source)
If (Not isArrayEmpty(workingset)) Then
workingset = atUnique(workingset)
End If

workingset = toArray(source.content)
If (Not isArrayEmpty(workingset)) Then
workingset = atUnique(workingset)
End If

Case Else

End Select ' Case sourcetype$

If (cachedb Is Nothing) Then
Set cachedb = directory
Set groupsview = Nothing
ElseIf (getDatabaseKey(cachedb) <> getDatabaseKey(directory)) Then
Set cachedb = directory
Set groupsview = Nothing
End If ' (cachedb Is Nothing)

If (groupsview Is Nothing) Then
extendedInfo$ = |View: | & VIEWNAME
Set groupsview = cachedb.GetView(VIEWNAME)
If (groupsview Is Nothing) Then Error ERR_MISSING_VIEW,MSG_MISSING_VIEW
End If ' groupsview Is Nothing

If IsScalar(workingset) Then workingset = toArray(workingset)

For idx% = LBound(workingset) To UBound(workingset)
extendedInfo$ = |Idx: | & CStr(idx%)
membername$ = Trim$(workingset(idx%))
extendedInfo$ = extendedInfo$ & Chr(10) & |Member Name: | & membername$
tag$ = UCase$(membername$)

If (Len(membername$) > 0) Then
If (Len IsElement(nongroupnames(tag$))) Then
If (Len IsElement(subgroupmembers(tag$))) Then
Set nvent = groupsview.GetEntryByKey(membername$, True)
If (nvent Is Nothing) Then
' membername is NOT a group
nongroupnames(tag$) = membername$

' membername IS a group
Set group = nvent.Document
subgroupmembers(tag$) = getDocItemValue(group, "Members")
End If ' (nvent Is Nothing)
End If ' (IsElement(subgroupmembers(tag$)))
End If ' (IsElement(nongroupnames(tag$)))
End If ' (Len(membername$) > 0)
Next idx%

' recursively expand all subgroups
ForAll subgroup In subgroupmembers
tag$ = ListTag(subgroup)
subgroupnongroupnames(tag$) = expandNamesList(directory, subgroup)
End Forall ' subgroup In subgroupmembers

' combine all the sub group members
ForAll subgroupnames In subgroupnongroupnames
If IsScalar(subgroupnames) Then
membername$ = Trim$(CStr(subgroupnames))
If (Len(membername$) > 0) Then nongroupnames(UCase$(membername$)) = membername$

ForAll element In subgroupnames
membername$ = Trim$(CStr(element))
If (Len(membername$) > 0) Then nongroupnames(UCase$(membername$)) = membername$
End Forall ' element In subgroupnames
End If ' IsScalar(subgroupnames)
End Forall ' subgroupnames In subgroupnongroupnames

result = atUnique(StringListToStringArray(nongroupnames))

If isRecursive Then incValue recursions%, -1
expandNamesList = result
Exit Function

On Error GoTo 0
If isRecursive Then extendedInfo$ = extendedInfo$ & Chr(10) & |Recursion Level: | & Format(recursions%, FORMAT_WHOLE_THOUSANDS)
enhLogException LIB_PREFIX, extendedInfo$
result = ""
Resume ExitPoint

End Function ' expandNamesList

Hope this helps!


Installing Traveler on CentOS 6 - Part IV

QuickImage Category Show-n-Tell Thursday Technical Linux Domino Traveler Admin

Part IV - Post Installation Configuration and Troubleshooting

This is Part IV in my series on installing IBM Lotus Domino and IBM Lotus Traveler on CentOS 6.

In this set of videos I cover initial configuration and troubleshoot a couple of issues with the Domino on Linux installation. Topics include:

  • Post Installation (Initial) Configuration of the Domino Server
  • Gnome Desktop Launcher Icon
  • Starting the Domino server for the first time
  • Correcting the File Handles Issue
  • Using gedit (the Linux Graphical text Editor)
  • Troubleshooting Linux Bindsock SMTP Port 25 issues
  • Accessing your Domino HTTP server using localhost

The next post in this series will cover the actual installation of IBM Lotus Traveler.

Part IV A - Domino Post Installation Configuration

Part IV B - Correcting the File Handles Issue

Part IV C - Troubleshooting Bindsock Port 25 Conflicts


Installing Traveler on CentOS 6 - Part 1

QuickImage Category Linux Video Domino Traveler Show-n-Tell Thursday

Part I - Installing CentOS 6

With CentOS 6 being released just a couple of weeks ago, I figured it was a good time to demonstrate installing IBM Lotus Domino and IBM Lotus Traveler on this particular flavor of Linux. I would have done it sooner, but I was on holiday and frankly fishing, kayaking, driving awesome cars, and shooting stuff beats computer geekery every single time.

This video kicks off the series. In this video I demonstrate the installation of CentOS 6. I'm using a Virtual Machine for the installation. VM Software is Oracle's VirtualBox. I've set it up for a single processor, 20GB HDD, 128MB Video Memory and 3GB RAM.

In my next video in this series I will demonstrate the steps necessary to prepare CentOS 6 Environment for an IBM Lotus Domino installation.



Domino 8.5.1 on OpenSUSE Parts 8.5.1A and 8.5.1B (Domino Setup)

QuickImage Category Show-n-Tell Thursday Technical Lotus Admin Linux

Finally Finished!

It's been a long road getting here, but we're now done (just in time for Lotusphere 2010).

Here's the last set in my series of "how to" videos on Setting up Lotus Domino 8.5.1 on OpenSUSE 11.1 (64 bit) in VirtualBox 3.0.8 on Microsoft Windows 7 (64 bit). These are parts 8.5.1A and 8.5.1B, Domino Setup. This set covers the setup / configuration of the Domino Server. Enjoy!

Part 8.5.1A - Domino Setup

Part 8.5.1B - Domino Setup


Domino 8.5.1 on OpenSUSE Parts 8A - 8C (Installing Domino)

QuickImage Category Show-n-Tell Thursday Technical Lotus Admin Linux

Welcome to my first SNTT post of 2010. I sincerly hope you all (all three of you) have a great New Year.

Here's the next set in my series of "how to" videos on Setting up Lotus Domino 8.5.1 on OpenSUSE 11.1 (64 bit) in VirtualBox 3.0.8 on Microsoft Windows 7 (64 bit). These are parts 8A - 8C, Installing Domino. This set covers the actual installation of the Domino Server (finally). Enjoy!

Part 8A - Installing Domino

Part 8B - Installing Domino

Part 8C - Installing Domino


Domino 8.5.1 on OpenSUSE Parts 7A - 7D (Preparing for Domino)

QuickImage Category Show-n-Tell Thursday Technical Lotus Admin Linux

Happy SNTT! and Merry Christmas!

Here's the next set in my series of "how to" videos on Setting up Lotus Domino 8.5.1 on OpenSUSE 11.1 (64 bit) in VirtualBox 3.0.8 on Microsoft Windows 7 (64 bit). These are parts 7D - 7D, Preparing for Domino. This set covers the final steps necessary prior to installing the Domino Server. Enjoy!

Part 7A - Preparing for Domino

Part 7B - Preparing for Domino

Part 7C - Preparing for Domino

Part 7D - Preparing for Domino


Domino 8.5.1 on OpenSUSE Parts 6A - 6E (Network Bridge and Shared Folders)

QuickImage Category Show-n-Tell Thursday Technical Lotus Admin Linux

Happy SNTT! Yes, I realize it's only Tuesday, but I'm going to be very busy for the rest of the week, so I figured I'd give you this one a bit early.

Here's the next set in my series of "how to" videos on Setting up Lotus Domino 8.5.1 on OpenSUSE 11.1 (64 bit) in VirtualBox 3.0.8 on Microsoft Windows 7 (64 bit). These are parts 6A - 6E, Network Bridge and Shared Folders. This allows you to connect to your guest OS from outside the guest OS, either from your Host OS or (if you choose to enable it) from another machine entirely. Additionally, I show you how to set up shared folders so your Host OS and Guest OS(es) can quickly and easily share files betwixt them. Enjoy!

Part 6A - Network Bridge and Shared Folders

Part 6B - Network Bridge and Shared Folders

Part 6C - Network Bridge and Shared Folders

Part 6D - Network Bridge and Shared Folders

Part 6E - Network Bridge and Shared Folders


Domino 8.5.1 on OpenSUSE Parts 5A - 5D

QuickImage Category Show-n-Tell Thursday Technical Lotus Admin Linux

Happy SNTT! Here's the next set in my series of "how to" videos on Setting up Lotus Domino 8.5.1 on OpenSUSE 11.1 (64 bit) in VirtualBox 3.0.8 on Microsoft Windows 7 (64 bit). These are parts 5A - 5D, VirtualBox Guest Additions. VirtualBox Guest Additions are installed AFTER installing the Guest O/S -they allow for a nice, clean, tight integration between the Host and Guest O/S. Enjoy!

Part 5A - VirtualBox Guest Additions

Part 5B - VirtualBox Guest Additions

Part 5C - VirtualBox Guest Additions

Part 5D - VirtualBox Guest Additions


Domino 8.5.1 on OpenSUSE Parts 4A - 4D

QuickImage Category Show-n-Tell Thursday Technical Lotus Admin Linux

Happy SNTT! Here's the next set in my series of "how to" videos on Setting up Lotus Domino 8.5.1 on OpenSUSE 11.1 (64 bit) in VirtualBox 3.0.8 on Microsoft Windows 7 (64 bit). These are parts 4A - 4D, Installing OpenSUSE. Don't worry, it's not that difficult. I had to break this into 4 parts (A-D) simply because of the YouTube time limit for video segments. Enjoy!

Part 4A - Installing OpenSUSE

Part 4B - Installing OpenSUSE

Part 4C - Installing OpenSUSE

Part 4D - Installing OpenSUSE


Domino 8.5.1 on OpenSUSE Parts 1 - 3

QuickImage Category Show-n-Tell Thursday Technical Lotus Admin

I know it's not Thursday, but yesterday was a National Holiday here in the US, so I'm posting this SNTT topic today instead.

I've started putting together a series of "how to" videos on Setting up Lotus Domino 8.5.1 on OpenSUSE 11.1 (64 bit) in VirtualBox 3.0.8 on Microsoft Windows 7 (64 bit). I'm sure that a lot of those in our Yellow Bubble have no need of this help because they're uber admins; but I figured the developer types (you know who you are) might find these useful. These are the steps that can be followed to get a dev/test server up an running on a laptop.


Part 1 - Introduction

Part 2 - Installing VirtualBox

Part 3 - Configuring the Virtual Machine


Kill All Profile Documents

QuickImage Category Show-n-Tell Thursday Technical LotusScript

Back off monkey-boy, I know it's not Thursday! Consider this a day late SNTT

This morning I found myself once again writing this agent. I've needed it several times in the past, but it was always such a quick one-off type of thing I never bothered throwing it in a reusable library. I posted it here so I can always find it again. I also figured somebody else might find it useful. If you like it, use it. If you don't like it, write your own.

Anyway, here's the code:

Option Public
Option Explicit
Use "enhLogClass"
' * Agent: KillAllProfileDocs
' * @author: Devin S. Olson
' * @created: 06 November 2009
' * @licence: WTFPL Version 2
' **/

Sub Initialize()
' * Purges all documents in the current database.
' **/
Dim nses As New NotesSession
Dim ndb As NotesDatabase
Dim collection As NotesDocumentCollection
Dim profile As NotesDocument
Dim result As Boolean

On Error Goto ErrorTrap

enhLogSetLogStackExceptions True
Set ndb = nses.CurrentDatabase
Set collection = ndb.GetProfileDocCollection()
Set profile = collection.GetFirstDocument()
While Not (profile Is Nothing)
enhLogAction ||, |Preparing to purge Profile Document with UNID: | & profile.UniversalID
enhLogAllDocItems profile
Set profile = collection.GetNextDocument(profile)
Wend ' Not (profile Is Nothing)

enhLogAction ||, |Purging | & Cstr(collection.count) & | Profile Documents|
Call collection.RemoveAll(True)

' success!
result = True

enhLogMethodResult ||, Cstr(result)
Exit Sub
On Error Goto 0
enhLogException ||, ||
result = False
Resume ExitPoint
End Sub ' Initialize



Javascript isArray(): How to determine if an object is an array

QuickImage Category Show-n-Tell Thursday Technical Javascript SSJS

Javascript is an incredibly powerful language. Much of this power is derived from Javascript's incredible extensibility, and extremely loose (some would say nonexistent) data typing. Variables can be switched from strings to objects to simple types to ...well, whatever you want. Functions can be objects, objects can be functions, variables can be functions, etc. This can turn developers into Djinn, giving us phenomenal cosmic powers; without necessarily being bound to an itty-bitty living space.

All this power does come with a cost though, which is mostly measured in bottles of Excedrin. Sometimes doing things that seem very simple and safe on the surface lead us to forget the Cthuluean Terrors hiding in the darkness below.

Arrays are one of these things. They seem simple; but the potential nastiness they contain can drive you mad.

Rule 1: An array is an object as an enumerated list of variables.

Memorize that. All arrays are objects. All arrays are enumerated lists.... of variables. Variables can be anything (strings, numbers, objects, functions, arrays....).

Rule 2: Javascript Arrays are not Associative.

An Associative Array is a list of variables which is indexed by keys. These keys can be numbers, strings, or other objects. The critical difference here is that a Javascript array is enumerated by number, and an associative array is indexed by anything. Because Javascript is so extensible, and because all Javascript arrays are themselves objects, it is very easy to construct something that appears to be and associative array:


How I get an Empty NotesDocumentCollection

QuickImage Category Show-n-Tell Thursday Technical

Tomorrow is Thanksgiving here in the US, so I figured I'd post this one a day early. I also posted this as a response to Andre Guirard's Lotus Domino Designer wiki post: Create an empty NotesDocumentCollection. I've reposted it here primarily so that I can format it in a manner more pleasing to my eye. (I'm weird that way). Enjoy:

Public Function getEmptyDocumentCollection(source As NotesDatabase) As NotesDocumentCollection
%REM This function intentionally has NO ERROR TRAPPING. Errors must be handled by the calling code.
' * Creates an empty NotesDocumentCollection from the source database.
' *
' * @param source NotesDatabase from within which to create the empty document collection.
' * @return NotesDocumentCollection containing zero documents.
' */

Dim result As NotesDocumentCollection

Set result = source.GetProfileDocCollection("*INVALID*")
While (result.Count > 0)
Call result.DeleteDocument(result.GetFirstDocument())
Wend ' (result.Count > 0)

Set getEmptyDocumentCollection = result

End Function ' getEmptyDocumentCollection


ActiveWorkspace Redux: Bugfix posted

Category Show-n-Tell Thursday Technical

Don McNally was kind enough to point out a bug in my ActiveWorkspace Prototype

Actually, he did more than that. He took the time to read the logs and figure out exactly what was causing the problem. He pinged me this morning to let me know about it; and to tell me exactly where to find the bug. I have corrected the code, and reposted the ActiveWorkspace Prototype to the downloads area. Thanks Don!

ACL Notes: Default would normally be Author access with the ability to create new documents. (Currently set to Manager). Database Managers need the [Admin] role.

Collaboration works!



Notes Client Active Workspace Prototype Available

Category Show-n-Tell Thursday Technical

Considering some of the discussions going on about enhancing / changing the Notes Client workspace, I am publishing this Active Workspace Prototype.

Right now it only works on Windows machines. It makes use of the Microsoft Web Browser control as the primary workspace component. The code is free to use as you see fit. If you like it, cool. If you hate it, I'm sorry. If you decide to use it in something, feel free to do so (just give credit where credit is due). Right now there is no about document (or any documentation whatsoever), and I realize the icons are pretty lacking.

As my buddy Nathan says, "it's probably not worth the effort needed to get this JUST RIGHT -- this mechanism has it's own annoying little quirks like Workspace and Bookmarks both do."
However, it also has some pretty cool capabilities. Test out the "Generate PIM ActiveLinks" and the "Generate ActiveLinks from Bookmarks" agents, and play with the drag and drop stuff.

ACL Notes: Default would normally be Author access with the ability to create new documents. (Currently set to Manager). Database Managers need the [Admin] role.

Special thanks to Chris Toohey for turning me on to the control, and Julian Robichaux for his very nice Java Progress Bar.

Prototype Zip file is available here.



Lotus Notes, Microsoft Web Browser Controls, Mapped Network Drives, and You.

QuickImage Category Show-n-Tell Thursday Technical

I know it is a day early for a SNTT post. If that really bothers you, come back tomorrow. I'll wait.

This post was inspired by two posts pointed out to me by Nathan, and a few phone calls with the Domino Guru himself, Mr. Chris Toohey. This is also an example of how well our community can collaborate to find a solution to a thorny problem.

The first post, Embedded Windows Explorer/File Browser for remotely-stored file resources in the Lotus Notes Client UIM, gives a basic explanation about the business need for using some form of an embedded file browser. The second, Sorting Hat - Embedded File Browser in the Lotus Notes Client UI - Flash Preview, gives a really good demonstation of the cutting / pasting & drag and drop capabilities available when using an embedded file browser.

I immediately got in touch with Chris, because this is something I can use right now, to solve business problems today. However, putting this to use is not really as simple as it should be.

The core of the solution relies on using an embedded control within a form. The embedded control has the official name of "Microsoft Web Browser"; with a class name of "Shell.Explorer.2". The primary purpose of the control is to allow a developer to embed a web browser control into an application. Savvy Domino developers (such as Tommy Valand, Tim Tripcony, or Nathan Freeman) will quickly realize that such a control should be able to pull double duty as an embedded file browser. And it can, (with a little bit of tweaking).

The control will, by default, work perfectly for local system files. The problem however, it that we need to use it to access mapped drives / network shares. Microsoft sees this as a security problem, and the February 2005 security hotfixes (and subsequent service packs) include security changes which effect embedded Microsoft Web Browser controls when interacting with mapped drives / network shares. The purpose of these changes is to disable drag-drop and cut-paste operations for such embedded controls. However, these security changes are not design or code changes; but rather changes to configuration settings. (Which, IMHO, is how it should be).

If you search the web for documentation on how to set the control to work with mapped drives, you will (as did I) find a whole bunch of solutions which involve custom log in scripts, registry changes, and even some (really scary) VB code samples which make real-time, undocumented changes to the registry. This is absolutely unacceptable to me.

Here is a fun idea! Tell a customer (while keeping a straight face) that in order to provide them with the functionality they want you are going to need code which can run with unrestricted access on all of their employees desktops which will modify the registry settings in real time. With no back out capability. And no documentation. Oh, I'm sure there are some folks who see this as a reasonable solution, but I'm not one of them.

So I set about the task of testing every single custom security configuration setting option (with restarts between tests) in order to find out what the settings need to be.

I'm happy to say, I figured it out.


Simple Solution for Web service is unable to create LotusScript object.

QuickImage Category Show-n-Tell Thursday Technical

Wherein I present the solution to an R7 conundrum

After a flurry of Yellow Bleeder chats and phone calls following yesterdays post, the true issue, and it's solution, have become apparent.

The issue is An LotusScript Class cannot be directly surfaced through an R7 Web Service running on a server. The class can however, be surfaced when the web service is running on a client machine.

This subtle difference is an important one, in that it can sneak up on an unwary developer and bring his or her work to a grinding halt. The reason is fairly simple. When you create a Web Service, you must define the Port Type class for the Web Service. The Port Type class is used as the basis for the WSDL generated by the service. If the method signatures of the Port Type class are changed in any way, the WSDL must be re-generated in order to incorporate the change(s).

When a developer is working on a Notes / Domino Web Service, the developer is using the Notes Designer client. When testing the Web Service on the local machine, the Designer Client will automatically regenerate the WSDL for the Web Service.

When testing the Web Service on a server, this regeneration never occurs. Which means that the Web Service attempting to surface a Port Type class defined in a LotusScript library breaks, without throwing any internal errors (ouch). The only error information available is passed back to the invoking client (the code attempting to connect to the Web Service), and is similar to this:

Web service SimpleEcho is unable to create LotusScript object for SimpleEcho datatype in method ECHO

Luckily, the solution is ridiculously simple.


Showing IBM Lotus Notes 8 On Linux Demo In Firefox On Suse Linux with Lotus Notes 8 on another Compiz Cube before Lotusphere. Whew! That's a mouthful.

QuickImage Category Technical Show-n-Tell Thursday BleedYellow LS 2008

Sorry about the poor audio quality. And the jiggly camera. Yes, I know the video quality is absolutely terrible.

But you gotta admit, it's still pretty cool.

BTW - My primary work environment (except for Notes Development -I'm still waiting for a Designer client) is now Notes 8 on Linux.

See y'all at Lotusphere!



What to do when every document in a view appears as a Replication Save Conflict

QuickImage Category Show-n-Tell Thursday

I ran into an interesting issue yesterday after having pushed some design changes to an existing production application database.

It seems that some of the users of the application, when opening some of the views, were seeing nothing but replication conflicts, instead of normal documents. Every single entry in the view appeared as a Replication Save Conflict. The offending views differed from user to user, and the Replication Conflicts View only contained two documents. The only thing that the users who were experiencing these symptoms had in common were:

  1. They were all accessing the database using a Notes Client (web users were unaffected)
  2. Their Notes Client versions were between 6.0 and 6.5.5 (primarily 6.5.3)
Refreshing the views (F9, Shift+F9, or even Ctrl+Shift+F9) at the client did no good, restarting the client (and even the machine) did no good, and even updating all the views from the server console load updall -R target.nsf did no good.

My first instinct was that the issue probably had to do with the version of the Notes Client being used (and in a small way I was correct); however in my haste to solve the problem (this is a really important production application) I failed to notice the most important clue: the offending views differed from user to user. I thought that perhaps the offending views contained some design elements (shared columns) or @Formula in either the selections, column formulas, or view actions that were somehow incompatible with Notes Client versions prior to 6.5.5. Our corporate standard version is R7.0.1, and the changes had been developed, tested, and UAT using this version.

After chasing several dead-ends, and doing a bunch of searching on the web, I realized the culprit was not incompatible design elements, but in fact the client side cache. The technote that helped me figure this out (while not explicitly mentioning the symptoms our users were experiencing) can be found here. It seems that the Notes Client 6 versions (up until 6.5.5) will sometimes refuse to release a cached design element (in this case the view design note), even when the design of a database has been updated. Restarting the Notes client (and even restarting the machine) does not solve the issue.


OpenLog gets Javascript

QuickImage Category Show-n-Tell Thursday

Unless you've been living under a rock for the last 3 years, you already know about Julian Robichaux and his amazing OpenLog tool.

Well, Julian has again raised the bar and added Javascript logging to OpenLog.

Kudos to Julian on a job well done. You can check it out here.



Incorporating Java Libraries in Lotus Notes

QuickImage Category Show-n-Tell Thursday

Reason #276 why Julian Robichaux rocks...

On 09/20/2006, Devin Olson wrote:

Hey there buddy.
Sorry to bother you, but I'm having some difficulties grokking Java within Notes.
Specifically, I can't seem to figure out how to reference a Java library from a Java Agent.

Client version: 7.0.1

From Designer Client, I created a Java library called Utilities.java
The code for this library is as follows:

import lotus.domino.*;

public class Utilities extends AgentBase {

   public Document getConfigDoc(String configKey) {

     // returns a document from the Database Configuration view.
     try {
       Session session = getSession();
       AgentContext agentContext = session.getAgentContext();
       Database db = agentContext.getCurrentDatabase();
       View view = db.getView("DbConfig");
       Document doc = view.getDocumentByKey("DbConfig", true);

       if (doc == null) {
         System.out.println ("could not get the config doc!");
       } else {
         System.out.println ("got the config doc!");
       } // if (doc==null)
       return doc;
     } catch(Exception e) {
       return null;
     } // try
   } // getConfigDoc
} // class Utility

I have successfully compiled and saved this library. I then created a new Java Agent called test_getConfigValue. The code for this agent is as follows (lines that reference the library are remmed out):

import lotus.domino.*;

public class JavaAgent extends AgentBase {

   public void NotesMain() {

     try {
       Session session = getSession();
       AgentContext agentContext = session.getAgentContext();

       // Utilities util = new Utilities();
       // Document doc = util.getConfigDoc( "DbConfig");
     } catch(Exception e) {
     } // try
   } // NotesMain()
} // class JavaAgent

I want to incorporate the afforementioned Java library into this agent. So I followed the instructions from Notes Designer Help (copied below):

Using a Java script library you can define common classes that you can then access from any Java agent.

    To use a Java script library in a Java agent
  1. From the Java agent programmer's pane, click Edit Project.
       The Organize Java Agent Files dialog box displays.
  2. From the Browse box, select Shared Java Libraries.
  3. Select the library you want to include.
  4. Click Add/Replace File(s).
       The library displays in the Current Agent Files list.
  5. Click Ok.

(See the attached file for a screenshot).

So, I would guess that I should now be able to reference the Utilities class and it's functions from within my new Java agent. This, frustratingly, is the reason for my email. For some reason, when I click "OK" (step 5 above), my agent doesn't seem to get updated. That is, it doesn't show the library as "referenced" on subsequent clicks of the Edit Project button. Am I missing something (not so) completely obvious? Is this normal behavior? Do you have any ideas as to what may be causing my problem?...

Julian's response was quick, concise, and solved my problem exactly....



QuickImage Category Show-n-Tell Thursday

Simple tip today. Keep an eye on the amount of free space you have left on your HDD. Trust me on this, running out of free space puts a real damper on your productivity.



Closing your XML when errors occur

QuickImage Category Show-n-Tell Thursday

I'm not going to give much of an introduction here, other than to point out that you should write your LotusScript code in such a way that it doesn't blow up. -All right, that wasn't really fair at all. Let me back up, and give you a bit of an explanation about this.

You can create a LotusScript agent in a database on a Domino server that will emit XML to a web browser. I'm sorry, but I'm not going to explain how to do that here. You should know that already. If there is a demand for it, I may post an entry on basic XML generation via LotusScript; but at this point I'm fairly sure it's not needed.

Anyway, on to what this posting is really about: writing your LotusScript agent in such a way that it emits valid XML even when an error occurs.

Here's the scenario: Your LotusScript agent has been called by some remote "thing" (web browser, XMLHttpRequest, etc.), and has started processing. It has already started returning information to the caller via print statements. Everything is going along great, and then it happens: an error occurs. Now, if you've been paying attention; your code is already robust and has error handling built into it. Perhaps you are even logging your error information using something like Julian Robichaux's OpenLog. Good for you. I'm going to give you two functions that you can use in conjunction with your error trapping / handling logic.

NOTE: (I emphasized the word "started" in the previous paragraph because there is actually quite a bit going on "under the covers" I don't want to get sidetracked by that right now -a full discussion of what the Domino Server is actually doing is way beyond the scope of a SNTT posting.)

On to the functions: You can use these to allow your LotusScript agent to finish up properly, even when an error occurs. Meaning, your code deals with the error, but what about the XML? Does your code finish the XML properly, or does it simply stop sending? A half-finished XML stream is worthless to the client / consumer. If an error occurs, you should still close up your XML. In fact, these two functions will also notify the user about the errors. So without further ado, here they are.


@IfError Obsolete in R7

QuickImage Category Show-n-Tell Thursday

When R6 came out, there were three new @Functions that I was really excited about.

There were a bunch of others, but these three in particular made me very happy. These were, (in order of my excitement level):

  1. @ThisValue
  2. @ThisName
  3. @IfError

@ThisValue and @ThisName made creating generic formulas a breeze, particularly with input translation & input validation. @IfError helped, as you can probably guess, to make error-trapping & handling a whole lot easier. From the day I installed R6 I started using @IfError in almost every piece of code I wrote. And since R6 came out, I've written a lot of code.

Today, while reading through the "Whats New in Domino Designer 7" area of Designer Help, I came across this little nugget:



Returns a null string ("") or the value of an alternative statement if a statement returns an error.

Note This @function is new with Release 6.

Note This @command is obsolete in Release 7.

@IfError( statement1 ; statement2 )


(Note: You can read the full help here.

In case you missed it, allow me to repeat (emphasis mine):

Note This @command is obsolete in Release 7.

Now, I don't want to go off on a rant, but...wait a minute, I absolutely want to rant about this.

"This @command is obsolete in Release 7." - WTF? They released a totally cool thing, and then made it obsolete in the next major release? Yes, I know how to work around this, but that's not the point. There were known issues with this @Formula (attention IBM documentation folks: This is NOT an @Command), and they were documented. Now, I understand how difficult it can be to fix a bug -especially those that involve mixed data types; but obsoleting the code instead of fixing it is absolutely unacceptable.

This isn't like when a small ISV screws up a minor product. This is friggen IBM! This is a HUGE, IMPORTANT product, with a MASSIVE installed customer base. Open up the checkbook, hire a few more developers, and FIX THE ISSUE.

As I stated earlier, I know how to work around this problem. I can very easily write error-trapping & handling code that doesn't use @IfError; but I shouldn't have to.

I can go through every application I've worked on since the release of R6 and modify every formula where I used @IfError; but I shouldn't have to.

I can explain to my boss and every one of my customers why I'm going to have to bill them for this special "maintenance work"; but I shouldn't have to.

IBM, please stop acting like that other major software company (you know, the folks in Redmond whose concern for their customers is best measured in micro-givashits). Pull your head out and FIX THE ISSUE.

Backwards compatible, my ass.



From the Archives: @DbName workaround for Web Clients - CGI

QuickImage Category Show-n-Tell Thursday

Ok, I blew it last week and didn't do a Show-n-Tell Thursday posting. This week I've been so busy I haven't had time to do one either, and it looks like I'm going to be just as or more so busy next week; so I decided to "pull one from the archives".

This one comes from when I was working as an instructor / courseware developer / application developer / systems administrator / webmaster for a (now defunct) company called Celebra Technologies (also called CelebraTech), which grew out of (also now defunct) InfoImage, Inc.

This tip was originally published in July of 2001 as part of a series of monthly "tech tips" I wrote for CelebraTech; which means we were still in the days of R5 -long before @WebDbName became available. Even though the specific need for the tip is now handled by @WebDbName, the techniques used in the tip are still, I belive, valid today.

If you are really interested, I've included a link (below) to a copy of the original, as published, Word document.


Detecting Browser Plugins, part 2

QuickImage Category Show-n-Tell Thursday

I'm currently posting this off-line, as the internet access in my lodge room is out. The router died yesterday after a power surge, and they won't have a new one installed until tomorrow (probably after I'm on my way home. Grr. Not having access is not at this point a critical or even a major problem, but it is frustrating.

This has been a really busy week, and I haven't been able to devote as much time as I'd hoped to getting this finished before today as I had planned. So, sadly, it isn't complete. But, this being Show-n-Tell Thursday, I'm going to post what I have so far.

Anyway, as I explained earlier, I've been working on some code to detect browser plugins. Frustrating doesn't even begin to describe how this has been. The hard part, however, is pretty much done. I'm not completely finished with it, and I'm most definitely not happy with it, but it is functional. What I have now is some code (a mixture of html, javascript, css, and vbscript) that will detect browser plugins (and has been successfully tested) in Microsoft Internet Explorer 5+, Netscape 4.6+, and Firefox 1.0.7 (I haven't tested in earlier versions of Firefox).


Announcing Show-n-Tell Thursday

QuickImage Category Show-n-Tell Thursday

Rocky and Bruce came up with a really cool idea, and I (as well as many others) am going to be participating.

The basic concept is that everybody who want to participate will post something "cool" they have accomplished, are working on, or just do on a regular basis. Ahem... before you go off on some wild tangent, this "something" should have something to do with Lotus Notes & Domino (or perhaps some of it's relatives, such as Sametime, Quickplace, etc.)

This doesn't have to be just development stuff. Admin, Policies & Procedures, etc are all fair game. Also, these postings aren't just limited to those of us who have blogs. If you have something you think is worthy of posting, send it to me (or anybody else who is participating), and it will get posted (assuming the owner of the particular blog is willing to post -most will be).

Sounds pretty cool, eh?

Now, I just need to come up with something for the first posting. Hmmm, perhaps I'll finish this teaser and post my solution then.



Class StringList

QuickImage Category Show-n-Tell Thursday

In today's post, Spanky's Place interviews Devin Olson about his current project.

SP: So tell us Devin, what are you up to?
DO: I've been attempting to port some more LotusScript code into VBA.

SP: Interesting. So, how is it going?
DO: @$%&*$!!!

SP: So it's not going well?
DO: Actually, it is going much better that could be expected. The two languages share a common root, and have almost identical syntax. The problem is that LotusScript has evolved a bit more than VBA, and has a richer object model.

SP: You mean that LotusScript is better than VBA?
DO: I wouldn't say better. The languages themselves are almost indistinguishable. In fact, porting from VBA to LotusScript is usually nothing more than a simple cut-and-paste operation. Going the other way, from LotusScript to VBA, can be more of an ordeal.

SP: And why is this?
DO: First and foremost, the Visual Studio IDE is #$$$!! &**^%# frustrating ^^*#$*&*@ hard to work with ^^@#%#* garbage %%@*#$, and usually takes quite a bit of time for a Notes developer to get comfortable with.

SP: OK, once we get past the IDE, are there any other problems?
DO: Yes, but these are normally due to differences in the object model of the two languages. Some things we take for granted and have come to rely on in LotusScript simply don't exist in VBA, and must be re-created or emulated in that environment.

SP: Can you give us an example?
DO: Sure thing.


Wowsers! A Tag Cloud!