TDIing out loud, ok SDIing as well

Ramblings on the paradigm-shift that is TDI.

Saturday, November 22, 2008

Troubleshoot the SyncDBfromSource AL in the Lotus Connections TDI Config: profiles_tdi.xml

Now that I have your attention, let me point you to this forum post where I describe the steps it takes to bring the SyncDBfromSource AssemblyLine -- the AL that forms the entire API into Connections' Profiles registry -- into the TDI Debugger in order to step through it for purposes of troubleshooting and adventure:

Google Group post about how to debug the Connections TDI ALs (near the bottom of the thread)

My wordy response is at the bottom of this thread. If you have an AssemblyLine that you wish to debug, but are still unable to (even after video #6 here) then let me know!

Monday, November 10, 2008 I remember

Remember to check out the FormEntry Connector. This is the perfect companion to the AL Debugger, letting you set up an infinite feed while you interactively set up Attribute values in order to exercise every corner of your AssemblyLine logic.

Plus, you can map out to the entryRawData parameter when this component is used in a Connector Loop, letting you use multiple Parsers on the same bytestream.

Very handy indeed!

New Component and Library .jar Files

Generally, adding a new component to TDI's library amounts to either 1) copying the relevant jar files to the [TDI Installation Folder]/jars sub-directory; or 2) leaving these files where they are and instead telling TDI where to find them.

This latter is done by setting the property found near the top of the file which is located in your Solution Directory.

According to the instructional comments found in the property file, you can set this property to a list of directory paths, or a list of files, or any combination of the two. For example,\Notes;CustomJars;C:\Drivers\jdbcDrv.jar

Using this property lets you keep custom jar  files either in place, or in a common area like the CustomJars folder I use. This can be preferrable to copying them into the TDI product installation folder.

Due to the mystical dance of Java loaders, sometimes these library files may need to be available to other loaders, in which case you end up having to do one or both of the following:

a). Modifying the PATH in the ibmditk and ibmdisrv files to include additional folders*.

b). Modifying the CLASSPATH line in these files for this same purpose.

I have several sub-folders to my own CustomJars directory, each containing the library files associated with a particular data source, like "Maximo", "Lotus" and so forth. TDI's loader checks all sub-folders under root directory specified, making it simple to keep these organized and backed up.

Note: libraries can be in zip files as well.

*Note: For Domino integration you will want to put the Notes path first: SET PATH=c:\Notes;%PATH% - since a little bird told me that only the first 128 chars are used by the Notes loader. At least for older versions.

...and I know there was something else I wanted to mention...

Thursday, November 6, 2008

Exceptional Solutions

There are two types: those that go beyond the call of duty to deliver scalable, available and maintainable integration; and those that are defined by the stack dumps of unhandled exceptions.

How do you keep an AssemblyLine in the air? By catching and dealing with exceptions yourself. This is broadly done in two ways:

1) By putting code in Error Hooks. At the very least, you should log the error. I tend to use a script function to handle this.

function logerror(msg) {
task.logmsg("ERROR", "@@ERROR - " + msg);
task.logmsg("ERROR", "@@ AL[Component]: " + task.getShortName()
+ "[" + error.getString("connectorname") + "]");
task.logmsg("ERROR", "@@ Operation: " + error.getString("operation"));
task.logmsg("ERROR", "@@ Message: " + error.getString("message"));
task.logmsg("ERROR", "@@ Exception: " + error.getString("exception"));

Of course, no error report would be complete without a dump of the various Entry objects available -- at least work and conn. Unfortunately, the dumpEntry() call does not let you set the log level. So I made my own:

function attList( e ) {
if (typeof(e) == "undefined" || !e)

var attnames = e.getAttributeNames();

var str = "";
for (var name in attnames) {
var att = e.getAttribute(name);
str += "@@ " + name + ": ";

for (var i = 0; i < att.size(); i++)
str += att.getValue(i) + " | ";

str = str.substring(0, str.length-3) + "\n";

return str;

function dumpEntry( logLevel, e, name ) {
if (typeof(e) == "undefined" || !e)

task.logmsg(logLevel, "\n@@ ******** Entry Dump: " + name + " ********\n"
+ attList( e )
+ "@@ ***************************************\n")

And then added it to my error function, making sure not to throw any exceptions whilst calling it:

function logerror( msg ) {
task.logmsg("ERROR", "@@ **** ERROR - " + msg);
task.logmsg("ERROR", "@@ AL[Component]: " + task.getShortName()
+ "[" + thisConnector.getName() + "]");
if (typeof(work) != "undefined" && work)
dumpEntry("ERROR", work, "Work");
if (typeof(conn) != "undefined" && conn)
dumpEntry("ERROR", conn, "Conn");
if (typeof(current) != "undefined" && current)
dumpEntry("ERROR", current, "Current");

Now it's easy to customize the format of the messages, as well as include other functionality if needed; for example, using a Passive Connector to write out error information, or using java.lang.System.out.println() to print messages to the command window where the TDI Server was started from.

2) Surround any script that can throw exceptions (like library calls) with a try-catch block:

try {
makeSomeCall(); // if this fails, catch below
} catch (exc) {
task.logmsg("@@ Error: " + exc);

If you don't handle it, then your AssemblyLine will stop running.

I'm just saying...

Saturday, November 1, 2008

Integrated Service Management (ISM) leverages TDI

TDI is bundled with IBM's ISM offerings to provide integration services for deployment of solutions like TADDM (System/Asset & Relationship Discovery Tool), CCMDB (Change & Configuration Management DB) and TSRM (IBM's Service Desk and Service Catalog product).

Here's a TSRM scenario captured on film: