Monday, August 15, 2011

TDI Sandboxing

I've been looking over the use of the Sandbox feature.
It's been around for sometime, although I'm not aware of many people using it.

Here's some scenarios of use:
  • Someone encounters a problem while developing an assemblyline in a closed environment. They need your help in debugging the Assemblyline, although aren't able to give you network access to the backend systems which the connectors are communicating with.
  • You have a resource which isn't always available on the network.
  • You want to debug the Assemblyline without having to connect to the Company's network, while at home in the evening.
By using the Sandbox feature included with the TDI Config Editor, we're able to create a repository of the sources which the Assemblyline interacts with. With the Sandbox and the Assemblyline, you can run the solution in another TDI CE & Server and debug the Assemblyline without the connectivity to the backend sources.



To Sandbox an Assemblyline, do the following:
NOTE: The Sandbox facility is not supported in AssemblyLines containing a Connector in Server mode, or an Iterator Connector with Delta enabled. The server will abort the running of the AssemblyLine if this is discovered.

Setup:
Define which resources you want captured in the Sandbox

The 'Database' name, used to store the Sandbox, will be the name of the directory created in the Solution directory. In this panel we also define which resources we want available to Record and to Playback.


Record Mode:
On the first initial run, you will have the Assemblyline in Record Mode.
This is done in the 'Specify Run Option' panel.



You'll see the following statement on the 'Record' run of the Assemblyline.
  • CTGDIS256I AssemblyLine AssemblyLines/'AL_Name' is started, recording to: 'Sandbox_Database_Name'.
  • You'll see the 'Database name' defined in the 'Sandbox Settings' panel appear as a directory in the Solution Directory.

Playback Mode:
Now set the Run Mode of the Assemblyline to 'Playback'.
Instead of the Assemblyline accessing the Active Directory as defined in the connector...the connector is simulated during playback.

The Active Directory system could be offline..or on a closed network....It just doesn't matter anymore..now we have a copy of the source and we can test this Assemblyline in any environment we want.

When the Assemblyline starts, you'll see the following line at the beginning of the ibmdi.log file.
  • CTGDIS257I AssemblyLine AssemblyLines/'AL_Name' is started, playing back from: 'Sandbox_Database_Name'.


Portability of the Sandbox:
As on of the benefits of the Sandbox, you're able to hand a few resources to another person and they're be able to run the Assemblyline without any of the backend resources/repositories. To move the Sandbox, you need to
  • Place a copy of the 'Sandbox' directory into the 'Solution_directory' on the other machine.
  • Import a copy of the TDI Eclipse Project or TDI Config XML into the other machine.
FYI: The table/view created in the Derby database held in the Sandbox directory is tied to the name of the Assemblyline. I discovered this when renaming an Assemblyline. So don't rename the Assemblyline, unless you want to dig into the database and do some modifications.
  • CTGDIS084I Initialization of ActiveDirectoryChangeDetectionConnector failed: java.lang.Exception: [ActiveDirectoryChangeDetectionConnector] CTGDIS025E Exception while loading configuration: java.lang.RuntimeException: CTGDIS593E Internal IDI proxy object exception: Table/View 'ASSEMBLYLINES_AD_DOMINOA_ACTIVEDIRECTORYCHANGEDETECTIONCONNECTOR' does not exist. ..






Monday, August 8, 2011

Syncing UserPhoto to jpegPhoto

A situation occurred when a customer wanted to know how they could pull a Domino RichText 'UserPhoto' field from Domino (names.nsf)...and sync that object to the 'jpegPhoto' attribute in the Domino Directory.

The main work here comes to convert from the RichText object to the byte stream we need for the jpegPhoto. In the example we did the conversation in an AttMap.


The AttMap had the following code to convert the UserPhoto object.

var someobj = work.getObject("UserPhoto");
if (someobj!=null) {
var objs = someobj.getEmbeddedObjects();
if ((objs != null) && (objs.size() > 0))
{
var em = objs.firstElement();

var fin=em.getInputStream();
var bytes = new byte[em.getFileSize()];
fin.read(bytes);
work.setAttribute( "jpegPhoto", bytes );
em.recycle();
}else{
task.logmsg("## NO UserPhoto for user: " +work.ShortName)
system.exitFlow()
}
}


Thursday, August 4, 2011

Misunderstanding of Initial DeltaStore Load

While working with a colleague we found the initial load of the DeltaStore to behave different then I initially expected.

On the initial load of the DeltaStore, if an skipEntry() occurs in the flow of the Entry it was my impression that the Entry would be ignored when the commit process to the DeltaStore occurred. I found I was wrong.

The skipEntry() method only makes the processing of data move to the next Entry. So even though the Entry is skipped, the note of the Entry is made on each successful read of the Entry. The sequence ID will be committed as defined in the Delta configuration(After every db operation, On end of AL cycle, On Connector Close, no autocommit).

For those entries where we do skipEntry() and do NOT want the Entry recorded in the DeltaStore, then a rollback of the sequence ID will need to be performed before the skipEntry() call.

A simple test iterated 2 entries...
The first entry was null and was recorded to the DeltaStore. The second iteration is notnull and expected to be skipped. Without the .rollbackDeltaState() the entry would still be recorded in the DeltaStore.

if (done1 == null)
{
done1 = "notnull";
thisConnector.rollbackDeltaState();
system.skipEntry();
}