task.shutdown(); // Invokes AL Shutdown Request Hook
And then we added real AL debugging and everything changed.
So I found myself doing more scripting...
To make my ALs easier to read and debug, I started using Script components (SCs) to define functions that I called from my Hooks. Larger chunks of code are split up into separate, clearly labeled SCs. For example, the snippet at the start of this article would have appeared in an SC called something like
Stop AL On Error.
Then I fire up the Debugger, step from script block to script block (since you can't step into them...yet) and examine
conn, inspect script variables, call any functions and just generally ensure the sanity of my AssemblyLine logic and the health of the data it's working with.
The QA of my solutions improves as well. Since the AL Debugger lets me change any value or invoke any function, it's easy to trigger and test particular parts of my code. I confess to even using the system.skipTo() call - the infamous TDI GOTO command - to move the "Execute Me Next" relay baton around in my AL.
So the first time I had to deal with Domino-specific Java types, I configured a Notes Iterator, fired up the Debugger, stepped to the
After GetNextHook and then told the Attribute value in question to tell me its Java class name:
rev = conn.getObject("$Revisions"); task.logmsg(rev.getClass().getName())Which I then looked it up in some Domino Java Classes documentation that Ken Lin pointed me at (thanks again, Ken). I also used
system.dumpJavaClass(rev.getClass().getName())to quickly get the list of publicly available methods:
[1:29:46 PM CEDT] E: system.dumpJavaClass(work.getObject("$Revisions".getClass().getName()) -> trueBingo! I could create a
CTGDIS827I Class name: lotus.domino.cso.DateTime.
doAdjust (int, int, boolean);
java.util.Dateobject by simply calling the Domino DateTime's
Then I asked the JDBC Connector to query the schema of the DB2 table, learning that the target column for this value was handled as java.sql.Timestamp, and I could easily create one of those like this:
new java.sql.Timestamp(rev.toJavaDate().getTime())Armed with Google in the one hand and my Norwegian Army Knife in the other, I happily whittled away at the solution, learning and correcting its design as I go.
The same goes for figuring out how to implement a REST-based web service, or scraping web pages for information, or provisioning accounts in Domino, Connections or Content Manager.
Scripted components, e.g. Connectors, Functions or Parsers, are trickier to debug since these execute in their own Script engines- but not impossible. Even though the Debugger gives you full access to the Script environment of the AssemblyLine itself, it can't access those of your scripted components. In order to debug their code, you need to bring it into the AL's environment, preferably as a series of SCs.
In this screenshot I am exercising the getNextEntry() function of Iterator Mode. Of course, selectEntries() has already been called by the
e = getNextEntry(); task.dumpEntry(e);You'd be surprise how much code you can squeeze into a single line :).
For example, I remember one project where an input data source was giving us over 150 Attributes. I used this one-liner to get a sorted list:
atts=work.getAttributeNames(); java.util.Arrays.sort(atts); for (a in atts) task.logmsg(a)TDI jockey Jon Elwood is currently building an AJAX interace to launch and monitor the progress of his AssemblyLines. You can imagine how handy the Debugger is for examining the incoming HTTP requests and interactively testing out return snippets of XHTML (or XML/JSON) by simply setting the value of the
http.bodyAttribute before End-of-Flow. Jon will be publishing a HowTo write-up on this that I am looking forward to.
So I guess that wraps up what has turned into an Ode to the AL Debugger. Just felt the need to share :)