Java's NotesException: .id, .text, and try/catch/finally
You probably know LotusScript error handling well: On Error Goto handler, jump to a label on error, read Err and Error$, maybe Resume Next to carry on. That model changes worlds in Java — nearly every lotus.domino method throws a NotesException, and it’s a checked exception: the compiler makes you either catch it or declare throws on the method. There’s no ignoring it.
This piece covers how you handle that exception in Java, and one rule that ties the whole “Java data layer” series together: the back-end objects you read about in the earlier parts, the ones that need recycling, get recycled in a finally — otherwise a thrown exception skips right past the recycle line.
TL;DR
NotesExceptionis checked: the docs say it “extends java.lang.Exception.” The compiler forces you to handle it — a different mindset from LotusScript’sOn Error, which is optional and ignorable.- It carries two public fields:
id(int, the Notes error code) andtext(String, the message). Verbatim: “NotesException.id, of type int, contains the error code.” - Branch on
id: comparee.idagainstNotesErrorconstants (e.g.NOTES_ERR_SYS_FILE_NOT_FOUND, value 4003) to tell “file not found” from other errors and handle them differently. - Put
recycleinfinally: so theDocument,DateTime, and iteration objects you created get collected whether the block finishes normally or throws. This is the series’ closing rule. - There’s also an
internalfield: the internal exception that caused the Domino one — usually null.
NotesException: checked, and carrying an error code
The docs define it in one line: “The NotesException class extends java.lang.Exception to include exception handling for Notes/Domino.” The load-bearing part is “extends java.lang.Exception” — it’s a checked exception, not a RuntimeException. That inverts the mindset from LotusScript: LS’s On Error is something you may choose to catch; Java’s NotesException is something the compiler forces you to. Call any lotus.domino method without handling its NotesException and the code simply won’t compile.
It carries two fields you’ll use constantly:
id(int): the docs say it “contains the error code” — the Notes error number.text(String): the docs say it “contains the error text” — the human-readable message.
(There’s also internal, of type Exception, wrapping the underlying exception that caused the Domino one; the docs note “Otherwise (and typically), this variable is null,” so you rarely touch it.)
Branching on id
text is for logging where a human reads it; to make the program branch by kind of error, you look at id. Notes error codes have named constants in NotesError, and comparing e.id against them identifies a specific error. The docs’ own example demonstrates one — when a named file doesn’t exist, “Notes/Domino throws the exception NOTES_ERR_SYS_FILE_NOT_FOUND (4003).” So you can write:
try { Database db = session.getDatabase("Server", "missing.nsf"); // ...} catch (NotesException e) { if (e.id == NotesError.NOTES_ERR_SYS_FILE_NOT_FOUND) { // file not found — this one I can handle (swap, create, or skip) } else { throw e; // an error I don't recognize — send it up }}That’s the Java version of “tell the errors apart,” taking the place of LotusScript’s Select Case Err.
The closing rule: recycle goes in finally
This is the rule that ties the whole Java data-layer series together. The earlier parts kept saying it: the Document, DateTime, and iteration objects in Java are back-end objects you have to recycle by hand. The catch is — if the recycle line sits inline with your processing, then the moment something throws a NotesException, execution jumps away and the recycle never runs. You think you’re collecting; on the error path you’re leaking.
The fix is Java’s finally: it runs whether the try block completes or throws. So the back-end object’s recycle goes there:
Document doc = null;try { doc = view.getFirstDocument(); String s = doc.getItemValueString("Subject"); // if this throws NotesException… // ... more processing ...} catch (NotesException e) { System.out.println("Notes error " + e.id + ": " + e.text);} finally { if (doc != null) doc.recycle(); // …this line still runs}Declaring doc outside the try and null-checking it in finally before recycling is the standard skeleton for Java Domino code. The site’s recycle() piece covers why you collect; this one adds where you collect once the code can actually throw.
A complete example
Putting the three together — checked exception, branch on id, collect in finally:
Document doc = null;try { doc = db.getDocumentByUNID(unid); process(doc.getItemValue("Items"));} catch (NotesException e) { // id for the program to branch on, text for a human — log both log.severe("Notes error " + e.id + ": " + e.text); throw e; // an error I don't recognize — send it up} finally { if (doc != null) doc.recycle(); // collected either way}The catch logs both id and text (id to branch on, text to read), and the finally guarantees that doc is collected whether things went fine or threw.
What about LotusScript and SSJS?
- LotusScript:
On Error Goto+Err/Error$+Resume. No checked exceptions, nofinally, and no manual recycle — memory collects itself, so LS has no “where to collect” problem. To imitatefinallyin LS, you usually put the cleanup at a label every pathResumes to. The site has a LotusScript error-handling piece. - SSJS / XPages: the same
lotus.dominounderneath, soNotesExceptionstill hasidandtext; but you catch it with JavaScript’stry/catch/finally, closer to the Java shape. Still recycle infinally, especially in XPages logic looping a big collection.