Closing your XML when errors occur
Category Show-n-Tell ThursdayI'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.
%REM This function INTENTIONALLY has no error trapping.
This function will generate an XML node by wrapping the content
within the node. If the content is blank, a blank node will be created
and returned. If the value for node is blank, an empty string ("") will
be returned. If the value for node contains blank spaces or contains
the substring "xml", an error will be raised.
Parameters:
Content:
String. The content to wrap within the node.
Node:
String. The node to wrap around the content.
Usage:
myNode$ = wrapXMLnode(myContent, myNodeName)
Any raised errors should be handled by the calling code.
%END REM
Const ERR_XMLNODE_INVALID = 1549
Const MSG_XMLNODE_INVALID = "The format for the XML node is invalid."
Dim sumPos As Integer
wrapXMLnode$ = ""
Content = Trim$(Content)
Node = Trim$(Lcase$(Node))
If (Node$) = "" Then Exit Function
sumPos = Instr(Node$, " ") + Instr(Node$, "xml")
If (sumPos > 0) Then Error ERR_XMLNODE_INVALID, MSG_XMLNODE_INVALID & | node="| & Node$ & |".|
If (Content$ = "" ) Then
wrapXMLnode$ = "<" & Node$ & " />"
Else
wrapXMLnode$ = "<" & Node$ & ">" & Content$ & "" & Node$ & ">"
End If ' (Content$ = "")
End Function ' wrapXMLnode
Function GetErrorXML ( intResult As Integer ) As String
%REM
This function generates the XML to be returned to the browser.
It relies on the existence of a globally declared List of Strings
(lstrErrors), which contains any errors that have occurred.
Errors within this list are ordered by error number (Err()).
%END REM
Const NODE_RESULT = |result|
Const NODE_ERRORLIST = |errorlist|
Const NODE_ERROR = |error|
Const NODE_ERRCODE = |errcode|
Const NODE_ERRTEXT = |errtext|
Dim strErrXML As String
Dim strErrCode As String
On Error Goto ErrorTrap
' make sure that strErrXML is blank
strErrXML$ = ""
' check for and add the error information first
If Islist(lstrErrors) Then
Forall strErr In lstrErrors
strErrXML$ = strErrXML$ & wrapXMLnode(wrapXMLnode(Cstr(Listtag(strErr)), _
NODE_ERRCODE) & wrapXMLnode(strErr, NODE_ERRTEXT), NODE_ERROR)
End Forall ' strErr In lstrErrors
End If ' Islist(lstrErrors)
strErrCode = Cstr(intResult)
ExitPoint:
' prepend the xml header
GetErrorXML = wrapXMLnode(strErrCode, NODE_RESULT) & wrapXMLnode(strErrXML$, NODE_ERRORLIST)
Exit Function
ErrorTrap:
LogError()
' Generate the Error XML
strErrCode = Cstr(Err())
strErrXML$ = wrapXMLnode(wrapXMLnode(strErrCode, NODE_ERRCODE) & _
wrapXMLnode(Error(), NODE_ERRTEXT), NODE_ERROR)
Resume ExitPoint
End Function ' GetErrorXML
Hope this helps!
-Devin
The Pridelands
Chris Byrne
Show n' Tell Thursdays


