This section contains the following sections to help you customize collaborations based on CollaborationFoundation:
This section describes coding practices to help you standardize your code with that in product-delivered collaborations.
It is good practice to establish naming conventions for use in your collaboration templates. The following list provides some naming conventions:
String sExceptionType Boolean bBranch
bSendEmail = getConfigProperty("SEND_EMAIL");
Process Designer automatically declares a variable of type BusObj called triggeringBusObj. This variable holds the flow trigger (usually a triggering event), which caused the scenario to execute.
Several situations might require you to work with the flow trigger even after it has been through processing such as having data added to it after being sent out through service calls, or having the values of attributes manipulated. Such situations include the following:
To handle these situations, it is recommended that you create an intermediate BusObj variable that is a copy of the flow trigger, then manipulate the intermediate variable and send it out through service calls as necessary rather than modify the flow trigger.
If your collaboration is configured to be a long-lived business process, however, the content of the flow trigger business object (triggeringBusObj) is not preserved across service calls. In this case, always make a copy of the triggering flow.
There are several APIs available that enable you to copy the contents of one business object into another and each has advantages and disadvantages; the sections Using the copy() method and Using the duplicate() method address each approach.
The copy() method can be used to copy the contents of one business object variable into another business object variable of the same type. It is recommended that you take this approach because the collaboration templates delivered by WebSphere InterChange Server do so, and having consistency between delivered and custom-built components results in greater maintainability.
To follow this approach you must instantiate a new BusObj object of the same type as the triggering business object; it is recommended that you perform the instantiation in the scenario definition of the scenario and that you name the variable that stores the copy processingBusObj. To satisfy these requirements and recommendations, add the following line of code to the scenario definition of the scenario:
BusObj processingBusObj; processingBusObj = triggeringBusObj.duplicate();
Next you must run the copy() method on the processingBusObj variable and pass the triggeringBusObj variable to it as an argument. It is good practice to do this in the first action node of the top-level diagram of the scenario--one that you dedicate exclusively to initializing variables. The example code below copies the contents of the triggeringBusObj variable into the processingBusObj variable:
processingBusObj.copy(triggeringBusObj);
For example, the code fragment below declares a variable of the same type as the flow trigger and sets its values by duplicating the values in the business object of the flow trigger:
BusObj processingBusObj; processingBusObj = triggeringBusObj.duplicate();
The collaboration uses processingBusObj to manipulate data as required. When it is ready to send the data to the destination application, the collaboration copies the intermediate variable to the ToBusObj variable. It uses ToBusObj in its service call to the destination application. The code fragment below shows the statement that copies the data to ToBusObj:
ToBusObj.copy(processingBusObj);
After the service call returns successfully to the collaboration, the collaboration copies ToBusObj's values to triggeringBusObj, as shown below:
triggeringBusObj.copy(ToBusObj);
WebSphere InterChange Server collaborations do not generally change the original value of triggeringBusObj until the collaboration has received the returned ToBusObj from the To port. Using the intermediate variable ensures that the collaboration changes the value of triggeringBusObj only after successfully receiving values from the destination application.
Catch exceptions at the level at which they occur, then raise them to the top process in the collaboration. By catching the exception, you can specify how to handle the exception and control how it appears to the user; for example, you can make clear the context in which the exception occurred. Moreover, creating action nodes for exception handling provides visual documentation of each place in the code where exceptions can occur.
In any collaboration, you must raise each trapped exception until it reaches the collaboration runtime environment. If you use a service call that triggers another collaboration, the calling collaboration must check for exceptions as a result of the service call.
To raise exception text to a calling diagram, declare separate string variables to store the message text and the exception type. For example, the following code declares two such string variables:
String sMessage String sExceptionType
Use branching to provide different behavior when the service call succeeds or fails. In the branch that handles failure, assign values into the two string variables. For example:
sMessage = currentException.getMessage(); sExceptionType = currentException.getType();
Before returning control to the process that made the service call, raise the exception. For example:
raiseException(ServiceCallException, 4000, SendRefBusObj.getType(), SendRefBusObj.getVerb(), SendRefBusObj.keysToString(), sExceptionType, sMessage);
The code above specifies error message 4000, which is the standard error message for collaboration failure. The message file includes the following text:
4000 Collaboration Failed: {1}.{2} with keys ({3}) synchronization failed and the exception is {4}.{5}. [EXPL] The business object could not be synchronized in the destination.
In the preceding text, the raiseException() method substitutes the values
shown in Table 14.
Table 14. Substituted values in raiseException() call
Variable | Substituted text |
---|---|
{1} | The value that SendRefBusObj.getType() returns |
{2} | The value that SendRefBusObj.getVerb() returns |
{3} | The value that SendRefBusObj.keysToString() returns |
{4} | The value in the sExceptionType variable |
{5} | The value in the sMessage variable |
If the process that makes the service call is not the topmost process in the collaboration, the process making the service call must raise the exception to its calling process. Each process above the calling process must also raise the exception so that the error message can be logged from the topmost process.
The flow of a collaboration diagram is often based on the value of a collaboration configuration property. The collaboration can use the property value to set a boolean variable, which it later uses to determine which path to take. For example, the following code declares and initializes a boolean variable named bBranch:
boolean bBranch = false;
WebSphere InterChange Server sets the value of the branching variable according to conditions in the code. These conditions may be based on the value of several boolean variables. For example, suppose the collaboration evaluates its CONDITION_TWO property only if its CONDITION_ONE property evaluates to true.
The code below bases a branch on the value of two boolean variables:
This code sets the value of bBranch to true if CONDITION_ONE evaluates to true and CONDITION_TWO evaluates to false; it sets the value of bBranch to false if CONDITION_ONE evaluates to false or CONDITION_TWO evaluates to true:
if (bCondition1 && !bCondition2) { bBranch = true; } else { bBranch = false; }
A wrapper collaboration is a collaboration that handles the verification or synchronization of a business object for another collaboration. The calling collaboration sends a top-level business object that is referenced on its own flow trigger to the wrapper collaboration.
For example, a SalesOrderProcessing collaboration can synchronize the generic Order business object. Generic Order contains references to a generic Customer business object, which represents the customer making the order. Moreover, generic Order contains an array of generic OrderLineItem business objects. Each OrderLineItem references a generic Item business object, which represents the items ordered.
To modularize collaboration logic, you can provide separate collaboration templates to process generic Order and the generic business objects that it references. For example, to process an Order that references Customer and Item business objects, you can provide the following templates:
Separating business object processing into different, specific collaborations not only enhances the reusability of each collaboration template, but also prevents two collaborations from modifying the same data at the same time. For more information, see "Problems in concurrent processing".
This section discusses the following common modifications to the CollaborationFoundation code:
Use the modifications presented in this section to standardize your customized collaborations with those delivered with the product.
A business object is said to have dependent data when it references another business object that affects its own processing. For example, assume that you want to synchronize Order, Customer and Item business objects at your site. Before your SalesOrderProcessing collaboration object synchronizes each Order, it needs to ensure that the Customer referenced by the Order already exists in the destination application. Furthermore, you want it to ensure that each Item referenced by each OrderLineItem also exists in the destination application, and perhaps even halt the Order's synchronization until you have verified that its referenced business object exists. In a case like this, the Order object is dependent upon the existence of its referenced Customer and Item objects.
Because WebSphere InterChange Server delivers several collaborations whose triggering business objects may reference a Customer or an Item business object, a single installation sometimes simultaneously runs more than one collaboration object that is trying to synchronize the same Customer or Item data. To maintain data consistency and prevent multiple collaborations from concurrently modifying the same instance of the same type of business object, delegate synchronization of referenced business objects to separate collaboration objects. Collaborations call intermediate wrapper collaborations to handle the verification or synchronization of business objects referenced on their triggering business objects. Wrapper collaborations facilitate data isolation in environments that run multiple collaborations.
Use wrapper collaborations to maintain data consistency in an environment that runs multiple collaborations. For example, assume that two CustomerSync collaboration objects run on the same installation. One runs in conjunction with SalesOrderProcessing, while the other runs independently. In this scenario, the independent CustomerSync collaboration object synchronizes Customer data between the same two applications as the SalesOrderProcessing collaboration object. If you use SalesOrderProcessing to delegate the synchronization of reference-valued Customer business objects to the intermediate CustomerWrapper collaboration object, the software provides event isolation. In other words, the system does not allow the standalone CustomerSync collaboration object to work on the same business object at the same time as the CustomerSync collaboration object called by SalesOrderProcessing.
For more information on synchronizing business objects referenced by a triggering business object, see Problems in concurrent processing.
You can extend CollaborationFoundation to delegate a dependency check to another collaboration. To do so, you must perform the following tasks:
To delegate dependent data, create a port for each dependent business object. Maintain consistency with other product-delivered collaborations by naming the new port ToBONameWrapper, where BOName refers to the dependent, reference-valued business object. For example, SalesOrderProcessing uses a port called ToCustomerWrapper to send reference-valued Customer business objects to CustomerWrapper.
Create one such port for each reference-valued business object to be sent to a wrapper collaboration. For example, SalesOrderProcessing also uses ports named SendContactRef and SendItemRef.
To delegate checking of a referenced business object to another collaboration, create a new collaboration configuration property. This property enables the person configuring the collaboration to specify whether the collaboration is going to verify or synchronize the referenced business object.
To maintain consistency with the product-delivered collaborations, name the new property VERIFY_SYNC_BOName, where BOName is the reference-valued business object. For example, SalesOrderProcessing contains a property called VERIFY_SYNC_CUSTOMER, which it uses to delegate checking of a Customer business object. Establish the possible values of this property as follows:
By default, the system sets a VERIFY_SYNC_BOName property to neither.
When a collaboration delegates an array of reference-valued business objects, it must be prepared to handle the synchronization or verification failure of any element in the array. The product-delivered collaborations provide configuration properties that enable you to specify how to handle the failure of individual elements of an array during verification or synchronization.
For example, the generic Order business object contains an array of OrderLineItem child business objects; each of these OrderLineItem objects can reference an Item business object. Therefore, the collaboration that handles the Order business object can delegate an array of Item business objects. Similarly, the generic Order business object contains an array of OrderContactRef child business objects, and each OrderContactRef can reference a Contact business object. Therefore, the collaboration handling the Order business object can delegate an array of Contact business objects.
The SalesOrderProcessing collaboration, which handles Order business objects, provides configuration properties that enable you to specify what happens when one or more referenced business objects in an array fail synchronization or verification.
One option is to stop synchronization of the triggering business object if any business object in a delegated array of referenced business objects fails synchronization or verification. Another option is to remove the failed business object from the array and continue synchronization of the triggering business object.
A collaboration evaluates options for handling a failed reference-valued business object only if it is attempting to verify or synchronize that business object. Therefore, the collaboration needs to evaluate a property that provides such options only if its corresponding VERIFY_SYNC_BOName property evaluates to verify or sync.
The collaborations provided with InterChange Server have two configuration properties that provide options when a referenced business object in an array fails verification or synchronization. One of these properties handles failed Contact business objects; the other handles failed Item business objects.
The following example demonstrates how an array of Contact business objects is handled. In this example, both SalesOrderProcessing and InstalledProductSync delegate arrays of reference-valued Contact business objects. Both use the FAIL_ON_CONTACT_ERROR property to determine the collaboration's behavior when the called collaboration fails to verify or synchronize one of the Contact objects in the array.
If you modify CollaborationFoundation to delegate an array of Contact objects, maintain consistency with other collaborations by coding your collaboration to evaluate FAIL_ON_CONTACT_ERROR only if VERIFY_SYNC_CONTACT evaluates to verify or sync and if ContactWrapper fails to verify or synchronize any of the referenced Contact objects. The product-delivered collaborations perform the following operations based on the value of FAIL_ON_CONTACT_ERROR:
By default, the FAIL_ON_CONTACT_ERROR property is set to true.
The following paragraphs demonstrate how arrays of Item business objects are handled. WebSphere InterChange Server business objects can contain an array of references to Item and Contact business objects. Therefore, each generic Order can reference an array of generic Item objects; you can configure SalesOrderProcessing to delegate an array of referenced Item business objects to ItemWrapper.
To handle errors for an individual Item that fails verification or synchronization, SalesOrderProcessing uses the FIND_ALL_ITEM_ERRORS property. The collaboration evaluates FIND_ALL_ITEM_ERRORS only if VERIFY_SYNC_ITEM evaluates to verify or sync and if ItemWrapper fails to verify or synchronize any of the referenced Item business objects.
Figure 10 illustrates the way in which CollaborationFoundation handles an array of referenced Item business objects when VERIFY_SYNC_ITEM evaluates to sync and FIND_ALL_ITEM_ERRORS evaluates to true.
Figure 10. Example of processing an array of referenced Item business objects
Collaborations perform the following operations based on the value of FIND_ALL_ITEM_ERRORS:
By default, the value of FIND_ALL_ITEM_ERRORS is false.
WebSphere InterChange Server delivers the generic Item business objects
listed in Table 15.
Table 15. Generic Item business objects
If a triggering business object can reference an Item business object, it is important to allow the person configuring the collaboration object to specify which type of referenced Item to verify or synchronize. The ITEM_TYPE property provides this functionality.
If the collaboration you build from CollaborationFoundation has a triggering business object that references Item business objects, extend your collaboration to use the ITEM_TYPE property. Define its set of values to include every type of Item business object available on your system.
By default, the ITEM_TYPE property is set to Item.
To examine or modify CollaborationFoundation's messages, edit its message file (collaborations\messages\CollaborationFoundation.txt). Maintain consistency with other InterChange Server collaborations by creating messages that provide information if any aspect of the dependency checking fails.
Because the WebSphere InterChange Server synchronization and wrapper collaborations provide their own error messages, collaborations developed from CollaborationFoundation need not contain error messages specific to each failed synchronization or verification of related business objects. However, these customized collaborations must explicitly handle the messages received from their called collaborations. For more information on handling these messages, see Raising exceptions.
To delegate checking of a referenced business object to another collaboration, you must create a collaboration scenario that evaluates whether the collaboration should verify or synchronize the referenced business object.
The scenario must check the value of the collaboration's VERIFY_SYNC_BOName property to determine whether the collaboration has been configured to verify or synchronize the referenced business object. You can also have the scenario perform other preliminary checking of the referenced business object before it calls a Wrapper collaboration.
For example, the following code enhances performance by preventing the collaboration from calling the CustomerWrapper collaboration unless it is truly required:
// Get the value of the configuration property String vsc = getConfigProperty("VERIFY_SYNC_CUSTOMER"); // By default, do not branch to Wrapper call. bBranch= false; // If VERIFY_SYNC_CUSTOMER evaluates to "neither" or // if the source application's business object does not contain the // Customer's primary key, do not change the value of bBranch. if (vsc.equals("neither") || (processingBusObj.isNull("CustomerID")))" {} else { // Get the Customer's primary key from the source // and destination application's business objects. // Note: The DestinationAppRetrieveBusObj variable // contains a value only if the USE_RETRIEVE property evaluates // to "true" and has already been processed. String sc=processingBusObj.getString("CustomerID"); String dc=DestinationAppRetrieveBusObj.getString("CustomerID"); // If the Customer's primary key is the same in both the // source and destination application (therefore, no need to // synchronize), the verb is Update, and USE_RETRIEVE evaluates // to "true", do not change the value of bBranch. if (sVerb.equals("update") && bUseRetrieve && sc.equals.(DC)) {} else { // If the verb is Create, or if the Customer's primary // keys are not identical and the verb is Update, call // the Wrapper collaboration. bBranch = true; } }
For an example of a collaboration template that includes the above code, see SalesOrderProcessing. Its Additional Processing 3 subdiagram includes code that checks the values of its VERIFY_SYNC_CUSTOMER, VERIFY_SYNC_ITEM, and VERIFY_SYNC_CONTACT properties to determine which of several paths to follow.
Because SalesOrderProcessing processes the USE_RETRIEVE diagram before processing the Additional Processing 3 subdiagram, its DestinationAppRetrieveBusObj variable can already contain the destination application's business object.
Most business objects reference other business objects whose types are different from their own. For example, Order references Customer, Contact, and Item. Order does not reference another Order business object. Because Order is not the only generic business object that can reference Customer, Contact, and Item objects, the collaboration that modifies Order needs to delegate processing of the referenced business objects to the appropriate wrapper collaborations. To maintain data consistency in environments that run multiple collaborations, no two product-delivered collaborations modify a business object of the same type.
The discussion of business object modification becomes more complicated, however, when analyzing the collaborations that modify InstalledProduct and Item business objects.
Like Order, an InstalledProduct business object can reference Customer, Contact, and Item. Unlike any other generic business object, however, InstalledProduct can also reference another InstalledProduct as its parent. Figure 11 illustrates the relationship between multiple InstalledProduct business objects.
Figure 11. Relationship between multiple InstalledProduct business objects
Figure 11 shows that the parent InstalledProduct does not contain its child InstalledProduct. Instead, the child contains a reference to its parent in its ParentId attribute, whose type is String. Any InstalledProduct that has a null in its ParentId attribute is at the top of its product hierarchy.
Item business objects also introduce a new level of complexity to business object modification. As shown in Table 15, WebSphere InterChange Server delivers a family of Item business objects. The business integration system handles Item business objects flexibly; collaborations use the value of their ITEM_TYPE property to determine which type of Item they are configured to handle.
Although one Item does not reference another as its parent, an Item business object can reference another business object in the Item family as its prerequisite. For example, ItemOrder and ItemPlanning can both reference ItemBasic as a prerequisite. By default, the PREQ_ITEMORDER and PREQ_ITEMPLANNING properties of the ItemSync collaboration specify ItemBasic as the prerequisite for both of these Item business objects.
When a business object references another business object of the same type or type family, the same collaboration that modifies the triggering business object can modify the referenced business object. In other words, the InstalledProductSync collaboration must delegate the handling of its triggering business object's referenced Customer, Contact, and Item objects.
However, InstalledProductSync can synchronize not only its triggering InstalledProduct but the parent InstalledProduct of the triggering business object, and the parent of the parent. Moreover, ItemSync can synchronize not only its triggering ItemOrder, but the ItemBasic prerequisite of the triggering business object. If the triggering business object's prerequisite has its own prerequisite, ItemSync can synchronize them all.
WebSphere InterChange Server provides two collaborations that recursively process a stack of business objects:
For example, assume that an organization that builds cars manages the components as separate installed products within a product hierarchy. In this case, the fuel injector is handled as an installed product, the parent of the fuel injector (the engine) is handled as an installed product, and the parent of the engine (the car) is handled as an installed product. To synchronize the fuel injector, InstalledProductSync builds a stack; the fuel injector is located at the bottom of the stack. The collaboration places the car at the top of the stack. When synchronizing, InstalledProductSync synchronizes the car first and the fuel injector last.
InstalledProductSync is based on the assumption that the parent of an InstalledProduct object must exist before the InstalledProduct is created, much as a boss must exist before an employee is hired.
ItemSync's process differs from the InstalledProductSync process as follows:
If you plan to modify CollaborationFoundation to perform recursive processing, examine the code for the InstalledProductSync and ItemSync collaborations. You can copy scenarios from those collaborations into the collaboration that you build from CollaborationFoundation. You can then modify the scenarios to meet your specific needs. For more information about these collaborations, see the reference pages for InstalledProductSync and ItemSync.