Level: Advanced Joey Wang (joeywang@ca.ibm.com), Technical Designer, IBM Luc Chamberland (lchamber@ca.ibm.com), Program Manager, IBM
01 Nov 2002 Creating an iterative activity flow that can store data retrieved for each iteration is not an easy task. The WebSphere Studio Application Developer Integration Edition 4.1 helps you do just that. This article shows you how to use the looping and data context features of the tools to build an enterprise service. It describes how to leverage the flow iteration, and includes a complete sample.
Introduction
When automating a flow of activities you often need to loop through a series of repetitive steps, rather than define the series of steps for each iteration. For example, imagine you need to create product catalog information by pulling together three different pieces of information: product ID number, product description, and product price. They come from three different sources, and the information for each product needs to be aggregated in a consistent manner. To implement this feature, you'll need to loop through your flow and temporarily store the collected information in shared data.
This article shows you how to use the looping and data context features of WebSphere Studio Application Developer (Application Developer) Integration Edition 4.1 to build an enterprise service (or simply, a service). You'll take a step-by-step tour that shows these features in the context of building a service flow. In this article, looping refers to looping within a flow, not a typical programming loop that you write with a programming language such as Java. You can download and view the sample code for this article. Three Java classes are used to simulate the external applications:
- Provide a list of product numbers
- For a given product number, return the corresponding product description
- For a given product number, return the corresponding price.
While this article provides some overview on the service and flow features of Application Developer Integration Edition, we assume you are familiar with the basic concepts of services and flows, and how to create flows in Integration Edition. (For review, you could go to the concepts in the online documentation or run through the samples on developing services.)
Creating enterprise service flows
In Application Developer Integration Edition, a flow defines the behavior of a business service using a microflow model. In the sample, as shown in Figure 1, the flow starts with a request for a list of product numbers. As the flow iterates for each product number, it invokes services to get the product description and price. When finished, all of the information for the products is printed to the console. (Of course, how the data is handled at the end of the flow is up to you. You might call a service to put the aggregated data into a database, or simply throw it away.) Figure 1. Example scenario

Creating services to access external applications
A Java class is used to simulate each external application, understanding that those external applications could be based on any technology (such as MQSeries messages, JMS, and so on). In this example, the classes are ProductList, ProductDescription, and ProductPrice. A service is then defined to act as an interface to that class. Use your service provider browser to easily create a service to access each class. Figure 2 shows the first step in creating a service definition based on the ProductDescription class. Figure 2. Creating service based on class
ProductDescription

When the three services have been defined, two Web Services Description Language (WSDL) files are generated for each service: a service definition file (*.wsdl) and a corresponding Java binding (*Java.wsdl). For this project you have:
- ProductDescription.wsdl
- ProductDescriptionJava.wsdl
- ProductList.wsdl
- ProductListJava.wsdl
- ProductPrice.wsdl
- ProductPriceJava.wsdl
Creating a flow for a single product
The Application Developer Integration Edition service flow editor provides a quick and easy way to define and test your flows. The following table shows a summary of the flow components supported in the editor.
Flow components
| Flow component icon | Component name | Description |  | Input node | The source and starting point of the flow. Can have any number of outgoing control and data links. |  | Output node | The end of the flow, collecting the flow results. Has one input terminal that can have any number of incoming control links, but only one incoming data link. |  | Activity node | Represents one of the operations that take place sequentially to satisfy the overall business process. Connected to other activity nodes with control links, and to datamap nodes with data links. |  | Looped activity node | An activity node that can be iterated so the operation executes more than once during the flow. |  | Control link | Determines the sequence in which activity nodes are executed. When the operation in an activity node is complete, a transition condition in the control link evaluates its results, and decides where to direct the flow. |  | Data link | Passes message types between activity nodes. Use a datamap node to process the message type into one that the target node can process. |  | Data context node | Stores data you want to use later within a condition or mapping. Connect a data context node to an activity node through a datamap using data links. |  | Datamap node | Transforms the source message type into a format the target node can understand. Connect them to activity nodes using data links. Can implement the mapping logic yourself using a Java method, or implement it using a transformer service. |
Once a service for each external application has been defined, you can construct a flow that retrieves price and product description information for each product, based on product ID number. Figure 3
shows the flow in the service flow editor. The Product_ID1 and
Product_ID2 datamap nodes each represent a single product ID number, and the Price_Desc datamap node represents the product description and price that correspond to that single product.
Figure 3. Create a product flow

Tip: Although a default datamap node has only one input terminal and one output terminal, you can add more input terminals (as is required for the Price_Desc node in Figure 3) by modifying the properties of the datamap node, as shown in Figure 4 below. Figure 4. Adding an input terminal to a datamap node

By having multiple input terminals, the datamap nodes can accumulate multiple outputs from different activity nodes. List 1. Data mapping of Price_Desc data map nodes

From the properties dialog, an input terminal can be removed as well. This technique is used in the following section. Creating the flow for multiple products
Of course, building a flow for just one product in the product list is only the first step. Now let's use the looping and data context features of Application Developer Integration Edition to build an iterative flow. Figure 5 below shows the preliminary form of the flow. The flow doesn't include initial input, but instead gets the list of product numbers from a service. The flow output is just the status of the flow. The following sections add more nodes to the flow to meet the requirements of our scenario. Figure 5. Preliminary CreateListProducts flow

Adding data context and looping to the solution
The CreateAProduct flow collects information for only one product. For this example, the flow must be called multiple times to get the price and description data for all the products on the list. As shown later in Figure 7, the output of the getProductList Service is a list of product numbers, which gets moved into the shared data context. The CreateAProduct looped activity node takes the first product ID as input (as opposed to the entire product ID list), so the First_product_ID datamap uses the data context. Similarly, because price and description information are not flow output of the CreateListProducts flow, Console_output does not take input from the CreateAProduct flow. Console_output gets all product information from the data context, prints all of the product information to the console, and generates status as the output of the flow. Before making CreateAProduct run multiple times, you need to define a common place to store the product information returned from the CreateAProduct flow. Adding data context to the flow
A data context provides a shared context where you can store flow data for later use. You need to create a data context in your example to store aggregated product data. You can connect the data context node to an activity node through a data map using data links. Note that this shared context can only be accessed from the parent flow, and not from any associated microflows. As a shared object, a data context is accessible for reading from any datamap node without having a link between the two nodes. For instance, First_product_ID in Figure 7
can access the data context node, even though a visual link is not drawn between the two. You can update the data context using either of these methods:
- Create a mapping from a datamap node (for example, Loop_env_prep)
- Iteratively update from the loop data context mapping, which associates a looping node with a data context.
It is a general rule that if the global data context is passed as an argument to the mapping method, then you can update the data context. For other methods, you can get the data context yourself by calling getDataContext(), noting that the node copy is read-only. The sample Java mappings for First_product_ID and Console_output show the two approaches. Adding looping to the flow
After the data context object is created for product information, use the property dialog of the node to specify that the createAProduct activity node should loop. As shown in Figure 6, select the Iterate this node checkbox and provide the data context object created above. Figure 6. Enabling looping on createAProduct node

Your flow should now look like Figure 7. Figure 7. Updated CreateListProducts flow

Using data context and looping
All objects stored in the data context object must implement the java.io.Serializable interface. In your sample, the ProductEntries object is used to store all product information. ProductEntries holds three pieces of information:
- an array of
Product objects
- a counter that points to the current
Product object
- the total number of
Product objects.
Both Product and ProductEntries classes implement the java.io.Serializable interface. List 2. Implementing java.io.Serializable interface

When working with looping in Application Developer Integration Edition, Java code can be used in several places: loop condition, loop mapping, and loop data context mapping. These events are called in the following order:
- Java mapping in Loop_env_prep, which create the initial
ProductEntries
in the DataContext object.
- Java mapping in First_product_ID, which retrieves the first product number from the
DataContext object.
- Java mapping in the loop condition, which determines if the loop should continue or not, based on the position of the pointer in the
Product collection.
- Java mapping in the loop Data Context mapping, which updates the
ProductEntries object with the price and description for current Product stored in DataContext.
- Java mapping in the loop mapping, which retrieves the next product number as input for the next iteration.
- Repeat steps 3, 4 and 5 until all product numbers are processed.
Running the sample
The source code for the sample is in two JAR files (you can download a zipped file that contains both JARs):
- ExternalApps.jar
- contains the three classes and service definitions that simulate the external applications.
- SampleFlows.jar
- contains both the CreateAProduct and CreateListProducts flows, as well as the
Product and ProductEntries classes that are used in Data Context.
To install the sample codes, create two enterprise service projects in the workspace (for example, called ExternalApps and SampleFlows). Then import the JAR files into the projects accordingly. You need to specify ExternalApps project in the Java Build Path of SampleFlows properties to avoid compilation errors, as shown in Figure 8. Figure 8. Setting build path in SampleFlows project

Deploy the CreateListProducts flow. In this sample, you deploy it as an EJB In Bound Binding type Services. (Refer to the online help for more information on deployment of a Service.) Once the CreateListProduct flow is successfully deployed, you can test it using the EJB Test Client in Application Developer Integration Edition. You can see the output in the console, as shown in List 3 below. List 3. Sample output

To illustrate that a direct data link is required to update the data context, Listing 3 shows that Console_output cannot find the gbc_newobj object created by First_product_ID.
Conclusion
In this sample, you probably noticed that the flow definition and the handling of shared data are completely separate. This separation provides a lot of flexibility. The definition of the flow is not constrained by the kind of data required for each activity, and the use of a shared data context ensures that the flow does not impact the availability of the data. The looping feature provides a mechanism to help the two work together.
Download | Name | Size | Download method |
|---|
| i-wsadieflow.zip | | HTTP |
Resources
About the authors  | |  | Joey Wang is a Technical Designer on the WebSphere Business Scenarios team. He prototypes advanced e-business applications using a variety of technologies on the WebSphere Platform. Previously Joey worked on the WebSphere Commerce Engagements team, helping customers develop e-commerce solutions. You can contact Joey at joeywang@ca.ibm.com.
|
 | 
|  | Luc Chamberland is Program Manager of WebSphere Business Scenarios. He works with various IBM teams to understand how customers use WebSphere products together, and provides recommendations to product groups on platform integration. Previously, Luc managed teams in the IBM Toronto Lab working on XML parsers within the Open Source community, and on the IBM VisualAge for Java product. He has written and presented on Java, XML, and Web Services. You can contact Luc at lchamber@ca.ibm.com.
|
Rate this page
|