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 Express 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 InterChange Server Express 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 = new BusObj(triggeringBusObj.getType());
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);
InterChange Server Express 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 8.
Table 8. 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;
InterChange Server Express 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".