Well today, I decided to add a call stack for those times the exception occurs in server script.
Where did I get the call stack from? I noticed that the call stack is displayed when an exception is thrown and we push it to the screen using TheApplication().RaiseErrorText(e), where e is the exception object. So I knew the call stack was available somewhere in that exception object.
Let's hack the exception object and see what it contains. A quick run of this code in the business service simulator was very revealing:
try { TheApplication ().RaiseErrorText ("Hello, World!"); } catch (e) { for (var key in e) Outputs.SetProperty (key, e[key]); }Here are the values that came out:
Property | Value |
errText | Hello, World! |
errCode | 22709 |
name | Error |
message | SiebelError: Hello, World!***RAISE ERROR TEXT*** Error near no filename:159 [RaiseErrorText()]. from no filename:159 [Service_PreInvokeMethod()] |
So I can see that the message property of the exception object houses the message I threw along with the call stack (at least when I threw that exception using RaiseErrorText()). So I can use that to my advantage.
Actually, the construct was something like this:
"SiebelError:" + <error message> + "***RAISE ERROR TEXT***" + <call stack>I didn't really have a need for anything before the call stack, so I stripped out everything up to and including the ***RAISE ERROR TEXT*** bit. So finally, here's the function I wrote to get the call stack.
function GetCallStack () { try { TheApplication ().RaiseErrorText (""); } catch (e) { return (e.message.replace (/^.*\*{3}RAISE ERROR TEXT\*{3}/, ""); } }If that return line looks Chinese to you it's because I am part Chinese. Allow me to translate...
I stripped out the junk prefix by using the string.replace() method to replace unwanted text with an empty string. The unwanted text was expressed as a regular expression, which basically reads, "Everything from the beginning of the line until ***RAISE ERROR TEXT***" So pretty straightforward logically.
Well there you have it! I'll save the primer on regular expressions for another day.
I've changed my mind on using RaiseErrorText() to throw the exception, after realizing that RaiseErrorText() adds the errText property to the exception where others do not (duh). Not that it makes that much of a difference, but to be really anal, my preference would be to use something shorter like:
ReplyDeletetry { x; } catch (e) { return (e.message.replace (/^[^\n]*\n/, "")); }
Where x is undeclared of course.