In Part 1 of this series, I introduced WebSphere Process Choreography in general, then developed a business process that meets the requirements of a simple scenario. To follow this tutorial in your own WebShere Studio Application Developer Integration Edition workspace, you must complete the steps in Part 1 of this series, as well as those in the article on creating a JCA-compliant resource adapter.
When complete, this process will:
-
Receive a list of product part descriptions in an XML document. Each part description has several attributes,
including
itemNumber,supplier,name,category, and so on. - Determine the price of each part in the list by querying an Enterprise Information System (EIS) that contains pricing information. This EIS will henceforth be called the pricing EIS.
- If the part's price is found in the pricing EIS, the process will place a message containing the part's information (including price) on the JMS queue jms/Q1.
- If the part's price is not found in the pricing EIS, the process will place a message containing the part's information on the JMS queue jms/Q2.
- Return a string that indicates the process completed successfully. The string should indicate the number of parts that were processed.
The process that was developed and unit tested in Part 1 receives an input message and generates the output message, but it does not query the pricing EIS, nor does it send messages to the JMS queues. I'll show you how to add that function.
In the article on creating a JCA-compliant
resource adapter, I showed you how to create a JCA adapter that queries the pricing EIS, and how to create
an Enterprise JavaBeans (EJB) component, ManagedTester, that invokes the JCA adapter. This process will
invoke the ManagedTester EJB using a Web service interface with an EJB binding.
In addition to the objects created in Part 1, you'll need to import an additional Web Services Description Language (WSDL)
file into your workspace. sendMessage.wsdl describes two different
JMS services: one that sends a message to the JMS queue jms/Q1, and
another that sends a message to the JMS queue jms/Q2.
Import the sendMessage.wsdl file into the com.test package of your service project.
You also need to create the WSDL files that describe the ManagedTester EJB. These WSDL files allow this EJB component to be invoked using a process service activity, as a Web service with an EJB binding. At this point, you might ask: "Why invoke the EJB using a service activity when it could instead be
invoked using a process EJB activity?" Good question! Here are some reasons why I prefer to invoke all external methods using service activities:
- Maintainability
- Using service activities provides a very loose binding between the process and the external methods that it calls. When the interface to an external method changes, the process need only modify the WSDL file that is mapped to the invoking service activity. A service that currently is invoked using an EJB binding might later change, so that it must be called using SOAP/HTTP, or JMS. By using service activities, the process can very easily accomodate such changes.
- Consistency
- If everything is a service, all invoking activities are handled the same way, have the same attributes, and so on. A process designed this way will closely adhere to the Services Oriented Architecture (SOA) model.
- Encapsulation
- The magic of WSDL files means that everything you need to know about an external method is contained in the WSDL file. When invoking an external method using an EJB activity, for example, you must manually supply the Java Naming Directory Interface (JNDI) name of the EJB.
Follow these steps to create the WSDL files that describe the ManagedTester EJB:
- Using the Business Integration perspective, in the left Navigator view, right-click on the testService project and select New > Service built from....
- In the New Service dialog, select EJB, and click Next.
- In the New EJB Service dialog, select DefaultEAR > MGDTest > ManagedTester and select the
getPrice(String)method, as shown in Figure 1. Then click Finish.
Figure 1. New EJB Service
You should now have three new WSDL files in the com.managedtest
package in the testService project:
- ManagedTester.wsdl
- ManagedTesterEJBBinding.wsdl
- ManagedTesterEJBService.wsdl
Activities that need to be executed multiple times within a process can be nested within a process loop. A loop activity contains Java statements that evaluate to true or false. The loop will continue to be executed until the loop activity's Java code evaluates to false.
In this scenario, you need to loop through the pricing EIS query and message sending activities once for each part included in the input message XML document. To do this, you need to create a process variable that you'll use to keep track of the number of times the loop has been executed, create a Java snippet that initializes that variable, create a loop activity, and finally add activities to the process loop.
For a discussion of the concept of process variables, see Part 1 of this series.
Loop activities contain Java code similar to Java snippet activities. A loop's Java code must evaluate to either true or false. If the result is true, the set of activities that make up the loop is executed; otherwise, the process continues with the next activity after the loop. In this case, the loop
activity should return false if the loop index variable is greater than or equal to the number of parts specified in the input message. Otherwise, it should increment the loop index.
- Create a loop index variable called
index. On the Variables panel of the process editor, click Add.... Complete the Add Variable dialog as shown in Figure 2, then click OK.
Figure 2. Add Process Variable
It's important to ALWAYS initialize your process variables. If you don't, the tooling won't show any task warnings, but you'll get runtime errors when you try to access an uninitialized process variable.
- Create an activity that initializes the loop index variable to the value of the input message's
count. Add a Java snippet activity immediately after the Input activity. In the new snippet's Java code window, right-click on a line between the user code begin/end comments, and select Update Variable > index. On the line between the two new lines of code, add theindex.setValueline, as shown below. This code sample initializes the loop index variable.// user code begin {Java Snippet Activity} IntMessage index = getIndex(); index.setValue(0); setIndex(index); // user code end
The result should look like Figure 3.
Figure 3. Java Snippet loop index variable
- Now we create a loop activity that returns
falseif theindexprocess variable is greater than or equal to the number of parts listed in the input message. Otherwise, it increments the loop index.Add a loop activity between the two Java snippet activities. In the loop activity's Java code window, right-click on a line between the user code begin/end statements, and again select Update Variable > index. Add additional loop activity Java code, as shown below:
// user code begin {Loop block Expression} IntMessage index = getIndex(); if (index.getValue() < getInput().getPartInformation().getPart() .length) { index.setValue(index.getValue() + 1); setIndex(index); } else { result = false } // user code end
The result should look similar to Figure 4.
Figure 4. Adding process loop activity
See Part 1 for a full discussion of invoking activities, terminals, and process variables.
Now, add activities to the loop itself. Click the Loop tab in the processor editor (highlighted in Figure 4) to see the loop process. The loop is simply a nested process. One difference, however, is that the loop activity's input and output activities have no implementations of their own. Within this loop, you'll add the activities necessary to query the pricing EIS, and to send the appropriate message to the appropriate JMS queue.
-
First, add the Web service activity that queries the EIS for price. Find the ManagedTesterEJBService.wsdl in the service project's
com.managedtestpackage in the left perspective window and drag it into the loop panel in the business process editor, as shown in Figure 6.You will see the Service Selection dialog, as shown below in Figure 5. The
ManagedTesterServiceonly offers one Port Type and one Operation, so click OK to accept these values.
Figure 5. Service Selection
- Now add the service activities that do the message sending. Find the sendMessage.wsdl file in the service project's
com.testpackage in the left perspective window and drag it into the loop panel in the business process editor. You will see another Service Selection dialog.The sendMessage.wsdl file contains two port types and two operations. One operation is
sendToQ1, which sends a message to the queue with JNDI namejms/Q1. The other issendToQ2, which sends a message to the queue with JNDI namejms/Q2.Select the port type Q1PortType and the operation sendToQ1, and click OK. Then create another service activity by dragging the sendMessage.wsdl into the process editor again and select the port type Q2PortType and the operation sendToQ2. The result should look similar to Figure 6.
Figure 6. Creating service activities
Assigning process variables to service activity terminals
You need to create process variables and assign them to the input and output terminals of the getPrice activity, and to the input terminals of the sendToQ1 and sendToQ2 activities. The sendToQ1 and sendToQ2 services are one-way operations that do not return any output. Therefore, the sendToQ1 and sendToQ2 activities that invoke these services have no variables associated with their output terminals.
There are two ways to create and assign new process variables:
- By selecting Assign Variable > Input > New... from the activity's context menu.
- By selecting Properties from the activity's context menu, clicking on Implementation to see the implementation properties panel, then clicking New Variable.
Now let's create and assign the process variables for the getPrice activity:
- Use one of the two methods described above to bring up the
Add Variable dialog for the getPrice activity's input terminal, as shown in Figure 7.
Figure 7. Add getPriceRequest variable
Notice that the default is the External type
getPriceRequest, which is exactly what you want. This is the input type defined in the ManagedTester.wsdl and is associated with thegetPriceoperation. - Click
OK to create a new variable called getPriceRequest of type
getPriceRequestand assign it to the input terminal of the getPrice service activity. - Bring up the Add Variable dialog for the getPrice activity's output terminal. Click OK to accept the default name getPriceResponse and default type getPriceResponse.
Next you'll create and assign the process variables for the input terminals of the sendToQ1 and sendToQ2 activities. Because the operations for these service activities use the same message type, both activities can share the same variable for their input terminals.
- Use one of the two methods described above to bring up the
Add Variable dialog for the sendToQ1 activity's input terminal, as shown in Figure 8.
Figure 8. Add myMessage variable
In this case, the default is the External type
myMessage. This is the input type that is defined in the sendMessage.wsdl and associated with thesendToQ1operation. - Click
OK to create a new variable called myMessage of type
myMessageand assign it to the input terminal of the sendToQ1 service activity. - Assign the same
myMessagevariable to the input terminal of the sendToQ2 service activity by right-clicking on the sendToQ2 activity, and select Assign Variable > Input > myMessage.
Adding Java snippet activities to the loop
The loop now requires two Java snippet activities: one to prepare the getPriceRequest message, and another to prepare the myMessage message.
Follow these steps to create the Java snippet activity for preparing the getPriceRequest message:
- Add a new Java snippet activity immediately to the left of the getPrice activity.
- Click Show Java to see the snippet's Java editor window. Right-click on an empty line between the user code begin/end comments and select Update Variable > getPriceRequest.
- On the blank line between the two new lines, add the code shown below:
//user code begin {Java Snippet Activity} GetPriceRequestMessage getPriceRequest = getGetPriceRequest(); com.pe.www.PartType partList[] = getInput().getPartInformation() .getPart(); com.pe.www.PartType part = partList[getIndex().getValue()]; String itemNumber = part.getItemNumber(); getPriceRequest.setItemNumber(itemNumber); setGetPriceRequest(getPriceRequest); // user code end
The result should look like Figure 9.
Figure 9. Java snippet setting getPriceRequest variable
Next, you need another Java snippet activity that will put data into the myMessage variable, used by the message sending services.
- Add a new Java snippet activity immediately to the right of the getPrice activity.
- Right click on an empty line between the user code begin/end comments and select Update Variable > myMessage.
- On the blank line between the two new lines, add code as shown below:
//user code begin {Java Snippet Activity} MyMessageMessage myMessage = getMyMessage(); com.pe.www.PartType partList[] = getInput().getPartInformation() .getPart(); com.pe.www.PartType part = partList[getIndex().getValue()]; String itemNumber = part.getItemNumber(); myMessage.setMessage("Item " + itemNumber + ": Price " + getGetPriceResponse().getResult()); setMyMessage(myMessage); // user code end
The result should look similar to Figure 10.
Figure 10. Java snippet setting message variable
Adding conditional control links
Now you need to add the if/then construct, which will cause the sendToQ1 activity to be fired if the part's price is found in the pricing EIS, and the sendToQ2 activity to be fired otherwise. To do this, you'll add control links and then make a couple of these links conditional.
- Add control links between activities so the loop's picture looks like Figure 11.
Figure 11. Adding control links
- The current loop would always fire both service activities. To add the necessary conditions, right-click the control link between the prepareMessage and
sendToQ1 activities and select Properties. Click Condition on the left side, select Defined Java, then click OK, as shown in Figure 12.
Figure 12. Creating conditional control links
Notice that there is now a Java editor window associated with the conditional control link. Similar to the loop activity's Java code, the conditional link will be followed if its Java code evaluates to
true. The ManagedTester EJB that you're using to access the pricing EIS will return the string "0.0" when it fails to find a price for a given part. Enter the following Java code between the user code begin/end comments://user code begin {Condition Expression} if (getGetPriceResponse().getResult().equalsIgnoreCase("0.0")) { result = false; } //user code end
- Right-click the control link between the prepareMessage and sendToQ2 activities, select Properties, and click Condition.
- Select Built-in, and select otherwise in the Value selection list. The otherwise attribute indicates that this control link should be followed if any of the conditions on other control links have failed.
Congratulations! The process is now complete.
| Name | Size | Download method |
|---|---|---|
| i-supply1c.zip | HTTP |
Information about download methods
- Download the source code used in this article.
- "Implement business processes using WebSphere Studio Application Developer Integration Edition, Part 1: The nuts and bolts of creating and unit testing a business process" (developerWorks, August 2003) by David Leigh describes how to create and deploy a business process, and how to test it using the built-in unit test environment.
-
WebSphere Application Server Process Choreographer Series contains several articles that discuss various aspects of business process development and runtime.

David Leigh is an Advisory Software Engineer in IBM Software Group's WebSphere Platform System House organization, located in Research Triangle Park, NC. His areas of expertise include WebSphere Process Choreographer, application and server security, high-availability, monitoring, IBM AIX, and Linux.
Comments (Undergoing maintenance)

