Error Handling in LotusScript Agents


Chuck Connell, CHC-3 Consulting



What We’ll Cover …

       Looking at the general principles of good software  error handling

       Identifying compile-time error detection in LotusScript (LS)

       Understanding runtime error detection and  reporting in LS

       Setting up error handlers in LS

       Dealing with special-case errors in LS

       Using an error log file in LS for periodic agents


Why This Matters

       Topics covered apply to all scripting situations

   Pull-down actions, email buttons, form/view buttons

   Form/view/database event triggers

   Periodic/nightly agents

       Admins need accurate and clear error reporting from server agents

   Often have a lot to review each morning

   Hard to diagnose cryptic errors in the server log

   Must know when something goes wrong, and just what the problem is

   Worst thing is not knowing there is a problem


Principles of Good Error Handling

       Catch errors as early as possible

   Design-time is better than code-time

   Compile-time is better than test-time

   Testing is better than production

   Catching errors earlier is cheaper and faster

       Report meaningful error messages

   Tell the user what is really wrong

   Suggest how to fix the problem

       Make full use of language’s error mechanisms

   LotusScript gives you many such tools

   We will show most during this talk


Compile Time, Option Declare

       Option Declare is the single most important line in any LotusScript code

   Forces all variables to be declared

   Put it in the Options code section (object)

   Catches many errors immediately

   It is OFF by default, should be ON

   However, developers can change the default in the Programmer’s Pane properties box


Compile Time, Explicit Data Types

       Variables default to Variant type

   Convenient, since Variants can be almost anything

   Also dangerous, since Variants can be almost anything

   Solution is to put an explicit type on all Dim statements


   Only small number of situations where Variant is really needed

   Can use suffix chars for typing (@, #, %, !), but hard to read and remember


Compile Time, Constants

       Use of constants for embedded text and numbers is SOP for all programming languages

       Somehow, LotusScript programmers often overlook this basic principle

       Why is it related to error handling?

   If you don’t do it, you will have hard-to-find errors

       Suppose there are 10,000 lines of code; you want to change the view name


Compile Time, Soft Field Names

       This topic is similar to using constants, except the constants are Notes field names

   Even programmers who use regular constants often overlook this application

       Benefit is the same as string/number constants

   When you want to change a field name (very common), it is much easier this way

       Suppose there are 100 references to many different field names, and you want to change them

       Code sample, named “Soft Fields”


Runtime, Check Notes Objects

       Whenever you work with a Notes object, make sure it really exists

       This coding mistake leads to errors that are tough to find

   The line with the runtime error is often far from the line with the coding error

       We cause runtime error by changing Tim’s name

       What line trips the runtime error reporting?

       Any missing object is reported immediately


LS Error Handlers, Theory

       When LS encounters a runtime error, it looks for a local user-defined error handler for that error code

       If no local handler is found, LS looks for one in the calling procedure, then the next up calling procedure, etc.

       If none are found, LS calls a simple built-in handler, then exits

       So how do you create an error handler…?

   Tell LS what error handler to use for each error code

   Create the error handler routines


Error Handlers – Sample

       Tells LS what to do with an error

   On Error Goto ErrorReturn

   Which errors?

üAll of them

   What to do?

üGo to ErrorReturn label

       Set up error handler

   Block of code from  ErrorReturn  to  Exit Sub

   Notice the Err, Error$, and Erl variables – defined within error handlers

   Notice the Resume statement – means that error handling is done

       You don’t need an error handler in every routine

   Can allow LS to “fail up” to a higher-level routine

   This is often good software design


Special Error Handlers

       Sometimes, an LS runtime error is not really an error

   You don’t want to exit or fail

       Code sample, named Special Errors

   On Error DIR_ERROR Resume Next

   Means: “For just error code 76, keep processing”

   Test by renaming the temp file

       Other points

   To get the relevant error code, you usually have to print it out

   Second general On Error erases the special instructions


Notes Error Log

       So, all this looks nice interactively…

       But what about nightly agents?

   Print statements from periodic agents are written to server log file

   These are tough to find in the morning

       How about a special log file for periodic agents?

       Code sample, named Error Log

   We will look at each line

   Log file uses ALOG4NTF template

   Code uses NotesLog class

   LogAction vs LogError

   Handles timestamps, error codes, and messages

       Can anyone see a problem with this code?


Notes Error Log, Caution

       Suppose your code has a runtime error before the error log is set up

       For industrial-strength code

   Create a temporary “print” handler at the start

   Then switch to the log handler after it is created


7 Key Points to Take Home

       Scan code for good LS error handling

       Are database, view, and field names soft-coded at the top?

       Is there an On Error statement near the top?

       Do early database and view opens have an immediate validity check?

       Do you see Option Declare?

       If this is a periodic server agent, do you see the NotesLog class?

       Insist on error handling for all server-based Agents