Thursday, November 17, 2011

Passing Initialization Parameters via tdisrvctl


I found the following process to work if you want to pass initialization parameters to a connector, via the command line.

For further details on parameters used for the 'tdisrvctl' command, refer to the docs.
Due to an APAR with the 'tdisrvctl' utiltity, you will need to be at TDIv7.1 FP0006 for the '-alop' parameter to parse correctly.


1.  Use the 'op-entry' object in the connector's configuration to access the passed in value.
All initialization attributes are to be prefixed with $init





























2.  When calling the 'tdisrvclt' utility,  use the '-alop' parameter to pass the value pairs to the server.
You can refer to the documentation link above for further details about this parameter.

Syntax:
bin\tdisrvctl -p 1099 -K serverapi\testadmin.jks
-P administrator -T testserver.jks -W server -op start -c config.xml -r SampleAL -alop $initialize {parameter:value;parameter:value}

Windows Exmaple:
\bin\tdisrvctl -p 1099 -K serverapi\testadmin.jks -P administrator -T testserver.jks -W server -op start -c config.xml -r SampleAL-alop $initialize {$init.oraId:oradmin;$init.oraPwd:abc123}

Linux Example:
./bin/tdisrvctl -p 1099 -K serverapi/testadmin.jks -P administrator -T testserver.jks -W server -op start -c config.xml -r SampleAL -alop \$initialize '{$init.oraId:oradmin;$init.oraPwd:abc123}'


------
Passing Initialization Parameters to the startAL() method via the tdisrvctl utility:
Here's a simple AL with the following in the AL Prolog.

//------------------------------------------------//
var stats;
var error;
var num;
var adds;
var result;

var OpEntry = task.getOpEntry();
var tcb = system.newTCB();

tcb.setConnectorParameter ( "JDBCconnector", "jdbcLogin", OpEntry.getString("$init.oraId"));
tcb.setConnectorParameter ( "JDBCconnector", "jdbcPassword", OpEntry.getString("$init.oraPwd"));

task.logmsg("**** Check Emp Status ******");
var check = main.startAL("AL1",tcb);
check.join();
result = check.getResult();
stats = task.getStats();
error=stats.getError();
num=stats.numErrors();

if (num == 0 ){
    task.logmsg("**** Running Emp Update ******");
    var empUpdate = main.startAL("AL2",tcb);
    empUpdate.join();
    result = empUpdate.getResult();
    stats = task.getStats();
    error=stats.getError();
    num=stats.numErrors();
    adds=stats.numAdd();

    task.logmsg("stats are: "+stats);
    task.logmsg("error is "+error);
    task.logmsg("numerrors is "+num);  
    task.logmsg("**** Run complete ******");
}else{
task.logmsg("**** Run ended ******");
        task.exit
}
//------------------------------------------------//


Commandline Command:

bin\tdisrvctl -p 1099 -K serverapi\testadmin.jks
-P administrator -T testserver.jks -W server -op start -c config.xml -r SampleAL -alop $initialize {parameter:value;parameter:value}



Monday, September 19, 2011

Solution Portability


Here's an additional option of making a solution easily portable/testable between QA, Dev, and Production environments.

When developing within the TDI Config Editor we want to make the most of the flexibility provided in Eclipse.  In this example we want to create a Property store for each environment which you'll be testing your Assemblyline against.

Here's an example of my Property Stores:



















-- Script References:
When referencing an property from a Property Store...reference the Property Name only.
Not the Property Store Name. With out declaring the Property Store Name, the TDI Server will pull the value from the Default Property Store.  Use setParam(string), not setParam(String,String) when referencing the property.
















-- 'Use Property' Reference:
When setting the value of a Connector's Field, there's many different ways to do this.
I believe the easiest approach is the 'Use Property' option.

When using the 'Use Property' option of a Field definition you'll see it automatically adds the Property Store Name to the Property Name.  This occurs when you select the property from your available properties.


By removing the Property Store Name (in the above example it would be 'Customer_Test:') the server will pull the Property Name from the Default Property Store.



-- Setting the Default Property Store
Now that we've set the solution to read the values from the Default Property Store, and not a particular Property Store we can easily and quickly redirect the direction of an AL just by selecting which Property Store we indicate as the Default Property Store.

To set the Default Property Store, just right click any of your Property Stores and select 'Default Property Store'.


On your next AL execution, the AL will read all it's property values from this particular Property Store.


-- Required Environment:



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();
}


Thursday, April 14, 2011

Server API inaccessible on SUSE

Through the process of working with TDI v7.1.0.3 and SUSE 10 today, I found that I had to enable the api.remote.bind.address= in the TDI's Solution.properties file.

By default the parameter is commented out. When commented out, the TDI CE wasn't able to connect to the TDI Server running on the SUSE 10 server.