Skip to main content

IBM DB2 Content Manager document routing, Part 2: A guided tour to API usage

Alan Yaung (ayaung@us.ibm.com), Senior Software Engineer, Content Management Development, Silicon Valley Laboratory, IBM
Alan Yaung is a senior software engineer of Content Management Development at IBM Silicon Valley Laboratory. He leads the Content Management Workflow Team. He has more than eight years of experience in product development of enterprise content management solutions. Alan is a Content Manager Certified Solution Designer. He also has over 20 granted and pending patents.
Allan Tham, DB2 Presales Technical Specialist, ASEAN Techline, IBM
Author photo
Allan Tham works as a DB2 Content Manager Technical Presales Support Specialist for Business Partners. He helps business partners solve a wide range of technical problems. Allan is certified for DB2 Content Management administration. Prior to joining IBM, Allan worked in an end-user environment, where he was an Oracle DBA for three years.

Summary:  This second article in a series of three articles will introduce you to IBM DB2® Content Manager® document routing and provide a claim process case study to show examples of implementation and usage of APIs.

View more content in this series

Date:  04 Aug 2005
Level:  Introductory
Activity:  752 views

Introduction

Efficient collaboration in the workplace contributes greatly to a company's success. But knowledge sharing and information are often lost when people cannot collaborate effectively, either within the same department or across departments. This results in dissatisfied customers and eventually leads to loss of revenue.

Today, most enterprise content management solutions provide a means for information to flow seamlessly to the intended recipient. The key to a successful business practice in a highly collaborative environment is the ability to route information, documents, and memos in a timely manner to users or groups of users holding different roles.

Workflow is an integral part of the IBM Enterprise Content Management solution. And there are different flavors of workflow available. IBM DB2® Content Manager® offers an integrated workflow solution, namely, built-in document routing. For more complex environments, customers can opt for WebSphere® MQ Workflow. This series of three articles will bring you a deeper understanding of IBM DB2 Content Manager document routing. They also provide a comparison between IBM DB2 Content Manager document routing and WebSphere MQ Workflow to help you better understand the differences and capabilities of each. The series of three articles are broken down as follows:

  • IBM DB2 Content Manager document routing, Part 1: A guided tour to process modeling
    • Introduction to IBM DB2 Content Manager document routing
    • Capabilities of IBM DB2 Content Manager document routing
    • What is new in IBM DB2 Content Manager document routing
    • Case Study - Claim Process
    • Implementation - Claim Process
    • Table of Comparisons - WebSphere MQ Workflow vs IBM DB2 Content Manager document routing
  • IBM DB2 Content Manager document routing, Part 2: A guided tour to API usage
    Using the same case study, this article demonstrates the usage of APIs for solution development.
  • IBM DB2 Content Manager document routing, Part 3: A guided tour to client usage Then experience the fruits of your labor by actually using the workflow defined in the same case study. The following client applications are considered in this article:
    • eClient - Web based client
    • pClient - Windows based client
    • CM Portlet - Portlet based client


Overview of the IBM DB2 Content Manager document routing API

Part 1 of this series discussed the capabilities of process modeling in DB2 Content Manager document routing. Much of the process modeling can be carried out through the graphical process builder in the System Administration Client. For client-related document routing tasks, a runtime API is provided for customers who wish to customize their applications. Though the default DB2 Content Manager Windows Client, eClient, and portlet exercise the runtime API, there are times when customers choose to develop their own client from scratch. This article, however, touches on the fundamentals of the document routing runtime API without getting into the very nitty-gritty aspect of it. You can use the walkthrough presented in the next section to jump-start a customized project.

We will briefly discuss the different classes and their main functions (refer to Resources section for the complete list)

  • DKDocRoutingServiceICM - This class provides the methods for routing and accessing workpackages and container data through a process. For example: start, terminate, continue, suspend, resume, listWorkPackages, and setWorkPackageContainerData.
  • DKDocRoutingServiceMgmtICM - This class provides the methods to manage the document routing definition classes: DKProcessICM, DKWorkNodeICM, DKWorkListICM, DKWorkFlowActionICM, and DKWorkFlowActionListICM.
  • DKProcessICM - This class represents a process definition, which contains the process diagram and route list of the process.
  • DKWorkNodeICM - This class represents a work node definition which details the expected or applicable tasks (such as workflow action list and library server exit) to perform at that particular step in a process.
  • DKWorkPackageICM - This class represents a work package for a routing task. It contains a persistent identifier for the document being routed, and information on the routing state (such as process name, worknode name, and completion time).
  • DKWorkListICM - This class represents a filtered view (based on criteria such as worknode and priority) for a collection of workpackages.
  • DKWorkFlowActionListICM - This class contains a collection of workflow actions. This enables a client application to display applicable workflow actions at a worknode.
  • DKWorkFlowActionICM - This class defines a workflow action that can be a dynamic linking library (DLL), an executable, a Java class file, and so on. This enables a client application to execute its own operation.


Prerequisites

In order to run the sample code provided in this article, you must:

  • Build the Claim Scenario from Part 1.
  • Set up a proper environment to run the code.
    • Windows® - Run cmbenv81.bat under the %IBMCMROOT%\BIN directory


IBM DB2 Content Manager Document Routing custom code walkthrough

This section shows you how Content Manager document routing can be used to accomplish various client tasks. The focus is on API calling with explanations given along the way. You can download the complete sample code from the Download section.

The sample program is written to exercise the simple auto claim process defined in the previous article, "IBM DB2 Content Manager document routing, Part 1: A guided tour to process modeling". The process diagram is shown in Figure 1 as a reference.


Figure 1. A sample claim process workflow
A sample claim process workflow

Connecting to the datastore

Connect to the Content Manager datastore.

// Connect to CM
dsICM = new DKDatastoreICM();
dsICM.connect(db,userid,pw,"SCHEMA=icmadmin");
System.out.println("datastore connected db " + db + " userid " + userid ); 

Creating a claim folder

Create a folder named XYZClaimFolder.

// Create a folder XYZClaimFolder
ddo = dsICM.createDDO("XYZ_ClaimFolder", DKConstant.DK_CM_FOLDER);

Calculating the claim amount

The generateClaimAmount method computes the claim amount based on two random numbers R1 and R2, where 0.0 < = R1, R2 < = 1.0

  • The first random number (R1) determines if the claim amount is less than $500 or greater than $500.
  • If less than $500, the claim amount is set to R2 * $500.
  • If larger than or equal to $500, the claim amount is set to $500 + R2 * $500.
private static double generateClaimAmount() {
  double randomNumber1 = Math.random();
  double randomNumber2 = Math.random();
  double claim_amount = 0;

  if (randomNumber1 >= 0.5) {
    claim_amount = 500 + Math.round(randomNumber2 * 500);
  } else {
    claim_amount = Math.round(randomNumber2 * 500);
  }

return claim_amount;

Setting folder attributes

Set the CLAIM_AMOUNT and XYZ_ClaimNumber attributes of the folder, and add the folder to the persistent datastore. The value of CLAIM_AMOUNT is set to the claim amount generated through the generateClaimAmount() method. The value of XYZ_ClaimNumber is set to an arbitrary string "2-123456".

1  claim_amount = generateClaimAmount();
             
   System.out.println("*** generated claim amount = " + claim_amount);
      
2  ddoFolder.setData((short)ddoFolder.dataId("CLAIM_AMOUNT"), new Double(claim_amount));
     
3  ddoFolder.setData((short)ddoFolder.dataId("XYZ_ClaimNumber"), new String("2-123456"));
      
4  ddoFolder.add();


In this example:
  1. Calculates the claim amount based on two random numbers (see "Calculating the claim amount" above for more information).
  2. Sets the claim amount.
  3. Sets the claim number.
  4. Adds the folder to the persistent datastore.

Creating a routing service object

Obtain a routing service object.

  System.out.println("Creating Routing Service Object");
1 DKDocRoutingServiceICM routingService = new DKDocRoutingServiceICM(dsICM);
  System.out.println("Created Routing Service Object");  


In this example:
  1. Creates a DKDocRoutingServiceICM object.

Cleaning up workpackages

Clean up all workpackages. This step is to make sure that there are no running processes.

   System.out.println("Deleting all workpackages...");
1  DKSequentialCollection coll = (DKSequentialCollection)routingService.listWorkPackages("AllWorklist", "");
   dkIterator iter = null;

   if (coll != null) {
2    iter = coll.createIterator();
     while (iter.more()) {
       DKWorkPackageICM wp = (DKWorkPackageICM)iter.next();
3      routingService.terminateProcess(wp.getPidString());  
     }
   }
   System.out.println ("All workpackages were deleted");


In this example:
  1. Creates a collection.
  2. Creates an iterator to loop through.
  3. Terminates the process.

Start SimpleAutoClaimProcess

Start the SimpleAutoClaimProcess process with the folder.

String workPackagePidStr = routingService.startProcess(pn, 
                                                       ddoFolder.getPidObject().pidString(), 
                                                       100, 
                                                       userid, 
                                                       null);
System.out.println("Started an instance of process " 
                   + pn 
                   + " Workpackage PID =" 
                   + workPackagePidStr);

Add documents to the folder

Prior to this, the folder is empty.

   // Add documents into the folder
1  addItemsToFolder(dsICM, ddoFolder);
   System.out.println("*** Documents were added into the folder");


In this example:
  1. Calls the method addItemsToFolder to add two documents into the folder. The addItemsToFolder wrapper code can be found in sampleDocRouting.java.

SubmitClaim worknode

Query the AllWorklist worklist and locate the workpackage at the "SubmitClaim" worknode.

   // at the SubmitClaim worknode 
   coll = null;
   iter = null;
   System.out.println("-------- Calling listWorkPackages --------");

1  coll = (DKSequentialCollection)routingService.listWorkPackages("AllWorklist", "");
   if (coll != null) {
      iter = coll.createIterator();
      while (iter.more()) {
        DKWorkPackageICM wp = (DKWorkPackageICM)iter.next();

2       displayWorkPackageInfo(wp);   

        // Query the AllWorklist worklist and locate the workpackage on the 
        // "SubmitClaim" worknode.
        // If process name is SimpleAutoClaimProcess and worknode name is 
        // SubmitClaim then continue the process
3       if (wp.getProcessName().equals("SimpleAutoClaimProcess") 
              && wp.getWorkNodeName().equals("SubmitClaim")) {
4         routingService.continueProcess(wp.getPidString(), "Continue", userid);  
          System.out.println("*** Called continueProcess on SubmitClaim");
          break;
        }
      }
   }


In this example:
  1. Creates a collection and later an iterator to loop through.
  2. Calls the method displayWorkPackageInfo. The displayWorkPackage wrapper code can be found in sampleDocRouting.java. It displays the information of the workpackage. The information includes the following:
    • Persistent ID
    • Priority
    • Time last moved
    • Suspend state
    • Notify state
    • Notify time
    • Resume time
    • Process completion time
    • Persistent ID of the item
    • Process name
    • Worknode name
    • Owner
    • Container data
  3. Queries the AllWorklist worklist and locates the workpackage at the SubmitClaim worknode. If the process name is SimpleAutoClaimProcess and the worknode name is SubmitClaim, continue the process.
  4. Continues the process.

WaitForReportAndEstimate collection point

At the collection point WaitForReportAndEstimate, the following code snippet will move the workpackage forward, if the criteria of the collection point are not satisfied.

coll = null;
iter = null;  
System.out.println("-------- Calling listWorkPackages --------");
      
coll = (DKSequentialCollection)routingService.listWorkPackages("AllWorklist", "");  
if (coll != null) {
  iter = coll.createIterator();
  while (iter.more()) {
    DKWorkPackageICM wp = (DKWorkPackageICM)iter.next();

    displayWorkPackageInfo(wp);   

    if (wp.getProcessName().equals("SimpleAutoClaimProcess") 
          && wp.getWorkNodeName().equals("WaitForReportAndEstimate")) {
      routingService.continueProcess(wp.getPidString(), "Continue", userid);       
      System.out.println("*** Called continueProcess on WaitForReportAndEstimate");
      break;
    }
  } 
}

Decision point 1: claim amount

At the first decision point of the simple auto claim process, the flow can either follow the path for claim amounts greater than $500, or follow the other path for claim amounts less than or equal to $500.

In this sample program, the approval decision is simulated based on random numbers. The method shown below simulates the approval decision.

private static DKNVPair generateApprovalDecision() {
  DKNVPair decision = null;
  double randomNumber = Math.random();

  if (randomNumber >= 0.5) {
    decision = new DKNVPair("APPROVE","ACCEPT");
  } else {
    decision = new DKNVPair("APPROVE","REJECT");
  }
  return decision;
}

The example below shows the program logic at the first decision point. It uses the generateApprovalDecision method to accept or reject the claims based on a random number, according to the following algorithm:

  1. If the process name is SimpleAutoClaimProcess and the worknode name is ReviewCredit, continue the process.
  2. If the process name is SimpleAutoClaimProcess and the worknode name is ReviewLargerClaim:
    • Set the APPROVE value based on a random number (Accept if random number > = 0.5, Reject if random number < 0.5)
    • Continue the process.
  3. If the process name is SimpleAutoClaimProcess and the worknode name is ReviewSmallClaim:
    • Set the APPROVE value based on a random number (Accept if random number > = 0.5,Reject if random number < 0.5)
    • Continue the process.
   // at the first decision point
   coll = null;
   iter = null;     
   System.out.println("-------- Calling listWorkPackages --------");

   coll = (DKSequentialCollection)routingService.listWorkPackages("AllWorklist", "");

   if (coll != null) {
     boolean ReviewCreditFound = false;
     boolean ReviewLargeClaimFound = false;

     iter = coll.createIterator();
     while (iter.more()) {
       DKWorkPackageICM wp = (DKWorkPackageICM)iter.next();

       displayWorkPackageInfo(wp);   

1      if (wp.getProcessName().equals("SimpleAutoClaimProcess")
             && wp.getWorkNodeName().equals("ReviewCredit")) {
          ReviewCreditFound = true;

          routingService.continueProcess(wp.getPidString(), "Continue", userid);   
          System.out.println("*** Called continueProcess on ReviewCredit");

          if (ReviewCreditFound && ReviewLargeClaimFound) break; 
       }

2      if (wp.getProcessName().equals("SimpleAutoClaimProcess") 
             && wp.getWorkNodeName().equals("ReviewLargeClaim")) {
          ReviewLargeClaimFound = true;

          DKSequentialCollection CNTcoll = new DKSequentialCollection();      
          decision = generateApprovalDecision();
          CNTcoll.addElement(decision);

          dkIterator CNTiter = null;
          if (CNTcoll != null) {
            CNTiter = CNTcoll.createIterator();
            System.out.println("-------- container data --------");
            while (CNTiter.more()) {
              DKNVPair CNTData = (DKNVPair)CNTiter.next();
              System.out.println("     Name=[" 
                                 + CNTData.getName() 
                                 + "]   Value=[" 
                                 + CNTData.getValue() 
                                 + "]");
              CNTData = null;
            }
          }

          routingService.continueProcess(wp.getPidString(), "Continue", userid, CNTcoll);
          System.out.println("*** Called continueProcess on ReviewLargeClaim");

          if (ReviewCreditFound && ReviewLargeClaimFound) break; 
       }

3      if (wp.getProcessName().equals("SimpleAutoClaimProcess") 
             && wp.getWorkNodeName().equals("ReviewSmallClaim")) {
          DKSequentialCollection CNTcoll = new DKSequentialCollection();      
          decision = generateApprovalDecision();
          CNTcoll.addElement(decision);

          dkIterator CNTiter = null;
          if (CNTcoll != null) {
            CNTiter = CNTcoll.createIterator();
            System.out.println("     Container data:");
            while (CNTiter.more()) {
              DKNVPair CNTData = (DKNVPair)CNTiter.next();
              System.out.println("     --- Name=[" 
                                 + CNTData.getName() 
                                 + "]   Value=[" 
                                 + CNTData.getValue() 
                                 + "]");
              CNTData = null;
            }
          }

          routingService.continueProcess(wp.getPidString(), "Continue", userid, CNTcoll);
          System.out.println("*** Called continueProcess on ReviewSmallClaim");

          break;
       }
     }
   }

CheckFraudHistory business application node

At the business application node CheckFraudHistory, if the user exit fails, continue the process.

// at the business application node
// if user exit fails, this will continue the process
coll = null;
iter = null;            
System.out.println("-------- Calling listWorkPackages --------");

coll = (DKSequentialCollection)routingService.listWorkPackages("AllWorklist", "");

if (coll != null) {
  iter = coll.createIterator();
  while (iter.more()) {
    DKWorkPackageICM wp = (DKWorkPackageICM)iter.next();

    displayWorkPackageInfo(wp);   

    if (wp.getProcessName().equals("SimpleAutoClaimProcess") 
          && wp.getWorkNodeName().equals("CheckFraudHistory")) {
      routingService.continueProcess(wp.getPidString(), "Continue", userid);      
      System.out.println("*** Called continueProcess on CheckFraudHistory");

      break;
    }
  }
}

Decision point 2: accept or reject

At the second decision point.

   // at the second decision point
   coll = null;
   iter = null;            
   System.out.println("-------- Calling listWorkPackages --------");

   coll = (DKSequentialCollection)routingService.listWorkPackages("AllWorklist", "");

   if (coll != null) {
     iter = coll.createIterator();
     while (iter.more()) {
       DKWorkPackageICM wp = (DKWorkPackageICM)iter.next();

       displayWorkPackageInfo(wp);   

1      if (wp.getProcessName().equals("PayClaimSubProcess") 
             && wp.getWorkNodeName().equals("PayClaim")) {
         routingService.continueProcess(wp.getPidString(), "Continue", userid);       
         System.out.println("*** Called continueProcess on PayClaim");

         break;
       }

2      if (wp.getProcessName().equals("SimpleAutoClaimProcess") 
             && wp.getWorkNodeName().equals("SendRejectionLetter")) {
         routingService.continueProcess(wp.getPidString(), "Continue", userid);   
         System.out.println("*** Called continueProcess on SendRejectionLetter");

         break;
       }
     }
   }


In this example:
  1. If process name is PayClaimSubProcess process and the worknode name is PayClaim, continue the process.
  2. If process name is SimpleAutoClaimProcess process and the worknode name is SendRejectionLetter, continue the process. The process is terminated.

SendThankYouLetter worknode

Calling Continue at SendThankYouLetter.

   // at the SendThankYouLetter worknode
   coll = null;
   iter = null; 
   System.out.println("-------- Calling listWorkPackages --------");

   coll = (DKSequentialCollection)routingService.listWorkPackages("AllWorklist", "");

   if (coll != null) {
     iter = coll.createIterator();
     while (iter.more()) {
       DKWorkPackageICM wp = (DKWorkPackageICM)iter.next();

       displayWorkPackageInfo(wp);   

1      if (wp.getProcessName().equals("SimpleAutoClaimProcess") 
             && wp.getWorkNodeName().equals("SendThankYouLetter")) {
         routingService.continueProcess(wp.getPidString(), "Continue", userid); 
         System.out.println("*** Called continueProcess on SendThankYouLetter");

         break;
       }
     }
   }   


In this example:
  1. If the process name is SimpleAutoClaimProcess and the worknode name is SendThankYouLetter, continue the process. The process is terminated.

Disconnecting from the datastore

Disconnect from the CM datastore.

dsICM.disconnect();

System.out.println("disconnected from ICM");

Sample output

Note: a typical execution of the sample program will generate the following output. Your Pid String, Item ID, and Component ID could be different of course.

datastore connected db icmnlsdb userid icmadmin
*** generated claim amount = 518.0
*** A folder was created
    Item Pid string =95 3 ICM8 icmnlsdb15 XYZ_ClaimFolder59 26 A1001001A05F20B51410I8968818 
A05F20B51410I896881 14 1025
    Item ID = A1001001A05F20B51410I89688
    Component ID = A05F20B51410I89688
    Version ID = 1
Creating Routing Service Object
Created Routing Service Object
Deleting all workpackages...
All workpackages were deleted
Started an instance of process SimpleAutoClaimProcess Workpackage PID =90 3 ICM8 icmnlsdb11 
WORKPACKAGE58 26 A1001001A05E06B64714I6505618...
*** Documents were added into the folder
-------- Calling listWorkPackages --------
-------- Workpackage Query --------
     PID = 90 3 ICM8 icmnlsdb11 WORKPACKAGE58 26 A1001001A05E06B64714I6505618 
A05F20B51411D360121 13 204
     Priority = 100
     Last Moved time = 2005-06-20-22.14.11.326000
     Suspend state = 0
     Notify state = 0
     Item PID = 95 3 ICM8 icmnlsdb15 XYZ_ClaimFolder59 26 A1001001A05F20B51410I8968818 
A05F20B51410I896881 14 1025
     Process name = SimpleAutoClaimProcess
     Worknode name = SubmitClaim
     Owner = ICMADMIN
*** Called continueProcess on SubmitClaim
-------- Calling listWorkPackages --------
-------- Workpackage Query --------
     PID = 90 3 ICM8 icmnlsdb11 WORKPACKAGE58 26 A1001001A05E24B71046G2636118 
A05F20B51412E676731 13 204
     Priority = 100
     Last Moved time = 2005-06-20-22.14.12.458000
     Suspend state = 0
     Notify state = 0
     Item PID = 95 3 ICM8 icmnlsdb15 XYZ_ClaimFolder59 26 A1001001A05F20B51410I8968818 
A05F20B51410I896881 14 1025
     Process name = SimpleAutoClaimProcess
     Worknode name = ReviewCredit
     Owner = ICMADMIN
-------- Workpackage Query --------
     PID = 90 3 ICM8 icmnlsdb11 WORKPACKAGE58 26 A1001001A05E06B65354A8617918 
A05F20B51412E562781 13 204
     Priority = 100
     Last Moved time = 2005-06-20-22.14.12.448000
     Suspend state = 0
     Notify state = 0
     Item PID = 95 3 ICM8 icmnlsdb15 XYZ_ClaimFolder59 26 A1001001A05F20B51410I8968818 
A05F20B51410I896881 14 1025
     Process name = SimpleAutoClaimProcess
     Worknode name = ReviewLargeClaim
     Owner = ICMADMIN
-------- Calling listWorkPackages --------
-------- Workpackage Query --------
     PID = 90 3 ICM8 icmnlsdb11 WORKPACKAGE58 26 A1001001A05E24B71046G2636118 
A05F20B51412E676731 13 204
     Priority = 100
     Last Moved time = 2005-06-20-22.14.12.458000
     Suspend state = 0
     Notify state = 0
     Item PID = 95 3 ICM8 icmnlsdb15 XYZ_ClaimFolder59 26 A1001001A05F20B51410I8968818 
A05F20B51410I896881 14 1025
     Process name = SimpleAutoClaimProcess
     Worknode name = ReviewCredit
     Owner = ICMADMIN
*** Called continueProcess on ReviewCredit
-------- Workpackage Query --------
     PID = 90 3 ICM8 icmnlsdb11 WORKPACKAGE58 26 A1001001A05E06B65354A8617918 
A05F20B51412E562781 13 204
     Priority = 100
     Last Moved time = 2005-06-20-22.14.12.448000
     Suspend state = 0
     Notify state = 0
     Item PID = 95 3 ICM8 icmnlsdb15 XYZ_ClaimFolder59 26 A1001001A05F20B51410I8968818 
A05F20B51410I896881 14 1025
     Process name = SimpleAutoClaimProcess
     Worknode name = ReviewLargeClaim
     Owner = ICMADMIN
-------- container data --------
     Name=[APPROVE]   Value=[REJECT]
*** Called continueProcess on ReviewLargeClaim
-------- Calling listWorkPackages --------
-------- Workpackage Query --------
     PID = 90 3 ICM8 icmnlsdb11 WORKPACKAGE58 26 A1001001A05E06B65840A5228118 
A05F20B51411D360121 13 204
     Priority = 100
     Last Moved time = 2005-06-20-22.14.12.899000
     Suspend state = 0
     Notify state = 0
     Item PID = 95 3 ICM8 icmnlsdb15 XYZ_ClaimFolder59 26 A1001001A05F20B51410I8968818 
A05F20B51410I896881 14 1025
     Process name = SimpleAutoClaimProcess
     Worknode name = SendRejectionLetter
     Owner = ICMADMIN
     Container data:
     --- Name=[APPROVE]   Value=[REJECT]
-------- Calling listWorkPackages --------
-------- Workpackage Query --------
     PID = 90 3 ICM8 icmnlsdb11 WORKPACKAGE58 26 A1001001A05E06B65840A5228118 
A05F20B51411D360121 13 204
     Priority = 100
     Last Moved time = 2005-06-20-22.14.12.899000
     Suspend state = 0
     Notify state = 0
     Item PID = 95 3 ICM8 icmnlsdb15 XYZ_ClaimFolder59 26 A1001001A05F20B51410I8968818 
A05F20B51410I896881 14 1025
     Process name = SimpleAutoClaimProcess
     Worknode name = SendRejectionLetter
     Owner = ICMADMIN
     Container data:
     --- Name=[APPROVE]   Value=[REJECT]
*** Called continueProcess on SendRejectionLetter
-------- Calling listWorkPackages --------
disconnected from ICM

Compiling the user exit code

The user exit code shown below is compiled as a dynamic linking library (for example: DLL).

   #include <stdio.h>
1  #include "WXV2TUE.h"

   #include <windows.h>
   #include <process.h>

   extern long WXV2TBAUE (ICMUSERSTRUCT *pCMStruct) {
     char envStr[256];
2    ICMCONTAINERDATA_STRUCT * pContainerDataStruct;
     FILE *_file;
       
3    strcpy(envStr, "c:\\temp\\test.txt");

4    pContainerDataStruct = 
       (ICMCONTAINERDATA_STRUCT *) malloc (sizeof(ICMCONTAINERDATA_STRUCT) * pCMStruct->sNumContainerData);

     _file = fopen(envStr, "aw");
     fprintf(_file, "*** Enterint Business Application node user exit\n");
5    fprintf(_file, "*** The number of container data structures from LS is: %d \n",
     pCMStruct->sNumContainerData);
6    fprintf(_file,"*** WP Comp ID from LS is: %s \n", pCMStruct->szWPCompID );
7    fprintf(_file,"*** WP Item ID from LS is: %s \n", pCMStruct->szWPItemID );

8    strcpy(pCMStruct->szRouteSel, "Continue");
     fprintf(_file,"*** Routed to the next node\n");
    
     fprintf(_file, "*** Leaving Business Application node user exit\n");

9    if (pContainerDataStruct != 0) free(pContainerDataStruct);

     fclose(_file);
    
     return 0;
   }


In this example:
  1. Includes the WXV2TUE.h header file.
  2. Declares a pointer to container structure, ICMCONTAINERDATA_STRUCT.
  3. Sets the output file path to "c:\temp\test.txt".
  4. Allocates memory to the container structure based on the number of container data.
  5. Prints the number of container data.
  6. Prints the component ID of the workpackage.
  7. Prints the item ID of the workpackage.
  8. Sets the route selection to "Continue".
  9. Frees the memory of the container structure.

Sample test.txt file

The test.txt file will be created under the directory c:\temp by the user exit code.

*** Enterint Business Application node user exit
*** The number of container data structures from LS is: 0 
*** WP Comp ID from LS is: A05F20B82328A18196 
*** WP Item ID from LS is: A1001001A05E06B72338I29494 
*** Routed to the next node
*** Leaving Business Application node user exit


Conclusion

This second article in a 3-part series on document routing serves as an introduction for those who are interested in developing document routing applications through application programming interfaces. It presented an overview on the DB2 Document Routing API, walking you through annotated sample code based on the simple auto claim process presented in Part 1. Whether you are a beginner or a workflow expert, this article on document routing API will benefit you.

Now that we have covered process modeling and API usage, the next article in this series will focus on client usage of document routing.


Acknowledgement

Special thanks to Ying-Pong Chen, Content Management Development, IBM Silicon Valley Laboratory, for taking his time to review this article.



Downloads

DescriptionNameSizeDownload method
C code sampleWXV2TBAUE.c2KB FTP | HTTP
document rounting samplesampleDocRouting.java29KB FTP | HTTP

Information about download methods


Resources

Learn

Discuss

About the authors

Alan Yaung is a senior software engineer of Content Management Development at IBM Silicon Valley Laboratory. He leads the Content Management Workflow Team. He has more than eight years of experience in product development of enterprise content management solutions. Alan is a Content Manager Certified Solution Designer. He also has over 20 granted and pending patents.

Author photo

Allan Tham works as a DB2 Content Manager Technical Presales Support Specialist for Business Partners. He helps business partners solve a wide range of technical problems. Allan is certified for DB2 Content Management administration. Prior to joining IBM, Allan worked in an end-user environment, where he was an Oracle DBA for three years.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Information Management
ArticleID=90981
ArticleTitle=IBM DB2 Content Manager document routing, Part 2: A guided tour to API usage
publish-date=08042005
author1-email=ayaung@us.ibm.com
author1-email-cc=thamawh@my.ibm.com
author2-email=thamawh@my.ibm.com
author2-email-cc=ayaung@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers