IBM WebSphere Developer Technical Journal : A guided tour of WebSphere Integration Developer -- Part 5

Business processes in a service-oriented world

This series explores a service-oriented approach to application integration using IBM® WebSphere® Integration Developer. The first three articles took you through a scenic tour of the product and helped you build a simple application. The previous article took you deep into the world of service-oriented business state machines. This article dives into how to build a business process, including when to use a business process versus a state machine.

Richard Gregory (gregoryr@ca.ibm.com), Staff Software Developer, IBM

Photo of Richard GregoryRichard Gregory is a software developer at the IBM Toronto Lab on the WebSphere Integration Developer team. His responsibilities include working on the evolution and delivery of test tools for WebSphere Integration Developer.



Jane Fung (jcyfung@ca.ibm.com), Staff Software Developer, IBM Toronto

Jane Fung's photo Jane is a Staff Software Developer at IBM Canada Ltd. She is responsible for developing the Business Process Executable Language (BPEL) and Business Rules debugger in WebSphere Integration Developer. Previously, she was the team lead of the WebSphere Studio Technical Support team. Jane received a bachelor in Electrical Engineering from the University of Waterloo in year 2000. She has extensive publishing experience, including numerous developerWorks articles. Jane was the lead author of an IBM Press book, An Introduction to Rational Application Developer, A Guided Tour.



Greg Adams (Greg_Adams@ca.ibm.com), Distinguished Engineer, IBM

Photo of Greg AdamsGreg Adams was the lead architect for the user interface in the award-winning Eclipse platform, and more recently, has been the lead architect and development lead in the core WebSphere Business Integration Tools, including WebSphere Studio Application Developer Integration Edition and WebSphere Integration Developer. Greg led the delivery of IBM's first complete services oriented architecture (SOA) tools stack and the first BPEL4WS standards supporting Business Process Editor; both critical deliverables in support of IBM's On Demand strategy.



Randy Giffen (Randy_Giffen@ca.ibm.com), Senior Software Developer, IBM

Photo of Randy Giffen Randy Giffen is a senior software developer is the usability lead for WebSphere Integration Developer and WebSphere Message Broker Toolkit. He was responsible for WebSphere Integration Developer's business state machine tools and the visual snippet editor. Prior to to this he was a member of user interface teams for WebSphere Studio Application Developer Integration Edition, Eclipse, and VisualAge for Java.



26 July 2006

Also available in Chinese

Introduction

Now that you have gotten a handle on the main concepts of WebSphere Integration Developer and its suite of tools from the first three articles, you are ready to dive deeper into business processes. If you haven't read the fourth article that covered business state machines, don't worry; you can go back and read it later because it is not a prerequisite. In fact, if you just skimmed over the earlier articles and didn't have time to complete the simple application, you can just download the OrderProcessing module at the end of this article and use that as the starting point to build the business process later.

As you may already know, a business process is any system or procedure that an organization uses to achieve a larger business goal. You can automate a business process or you can involve a number of steps that need to be manually completed by one or more users. Business processes can be short running, or take hours, days, weeks or more to complete. Business processes are great for driving your business, but building them within a service-oriented architecture (SOA) puts your application into overdrive. After all, the real power comes from being able to integrate the processes seamlessly with other components and modules to automate getting work done.

With WebSphere Integration Developer, you can create a business process using the business process editor. A business process provides the primary means to coordinate enterprise services and describe your business logic. So, what does that mean? Well, a business process is an implementation of a service component that consists of a series of steps or activities that are run in a specific order. The activities can call other services, perform computations, or do just about any kind of programming work. The activities in a process can run sequentially or in parallel. You can also implement branching or looping in the flow of control between activities. A business process can be part of a larger business process, and it can contain nested business processes.

In the sections that follow, you will learn about:

  • The parts that make up a business process
  • Business process concepts
  • The business process editor
  • Building your own business process.

Anatomy of a business process

If you read the previous article about business state machines, you might be interested to learn that business state machines are a special case of a business process. To let you in on a little secret, under the covers a business process actually implements a state machine. Both business state machines and business processes are important techniques for defining your business logic. You are probably scratching your head and wondering, "If they are both important yet similar, how can I expect to know when to use a business process instead of a state machine?"

Well, if your business logic involves responding to events, and the response depends on the current state of the process, then it may be useful to implement the logic as a business state machine. State machines are also useful when the logic is cyclic in nature; that is, where an object or part of the system goes through a series of states repeatedly. For example, a vending machine awaits coins, then lets you to buy a drink, then returns your change before it once again waits patiently for its next junk food victim. Business processes, on the other hand, are useful for all other cases, especially cases where your business logic is a series of steps that you want to execute sequentially or in parallel.

SOA consists of many services connected together that talk to each other to achieve an overall goal. As you know from previous articles, a business process is one way that you can implement a service component.

A business process consists of the following elements, which we will explore in the upcoming sections:

  • Activities
  • Partners
  • Variables
  • Correlation sets
  • Handlers.

Activities

A business process component consists of a set of activities, each of which does some work. Together, these activities represent your business logic. The work each activity does is completely up to you. It could involve performing a computation, calling a business partner's service, or perhaps asking a person in the organization to perform some manual work.

You can break each activity down into still more activities. For example, an activity in your process might be to bill a customer for an order. Prior to your company's going cutting-edge, the overall billing activity might have been broken down into looking up the customer's address, printing an invoice, and then mailing it. The first two activities might be service calls, while the latter would probably be a human task. Activities can execute sequentially, or in parallel. For example, an activity in your ordering process might notify your inventory system that an item needs to be re-ordered while the shipping activity is executing in parallel.

For each type of activity, you can enable event monitoring using the Event Monitoring tab in the properties view. This enables your process to emit Common Event Infrastructure events as it runs. Depending on the activity type, different options are available. For example, an invoke activity can emit entry and/or exit events. An invoke activity emits an entry event when a business process is about to execute or enter the invoke activity, whereas it emits an exit event when the business process is about to finish the execution of the invoke activity.

You can add activities to a process by selecting them from the palette and dropping them onto the business process editor canvas, or right-clicking on the canvas and selecting Add - [activity type].

Now let's look at the various types of activities that you can use in your processes.

Service activities

Service activities enable your business process to communicate with other services and vice versa. Without service activities, your process would live a lonely, quiet life. There are three types of service activities:

  • Receive
  • Reply
  • Invoke.

Receive activity

A receive activity is an entry point to a process; it is the point where the process starts or continues. You need one receive activity per operation you define in the process's interface. In the process editor, you can specify which operation corresponds to which receive activity. That means that when a call is made to one of the process's operations, the corresponding receive activity accepts the call, and the process continues running from there. A process requires at least one receive activity to start. A receive activity can also occur in the middle of a business process. In this case, if the process encounters a receive activity while it is running, the process stops and waits for the corresponding operation to be called.

An example should make this easier to understand. In the example in Figure 1, SimpleProcess has an interface that has two operations: start and continue. These operations are receive activities that run in sequential order. Let’s take a look at what will happen when the process runs.

  • When another component calls the start operation, it creates a a new process instance.
  • Next, the input parameter, which you can see at the bottom of the figure, will have its value assigned to the variable Input1. The input and output variables are created for you when you create the process.
  • The CallService activity runs and, when it finishes, the process stops running until it receives a call to the continue operation.
  • Once a call is made to the continue operation, the process continues to the PrepareResponse activity.
Figure 1. Service activities
Service activities

Reply activity

When a receive activity belongs to a request-response operation, a reply activity returns the output of the operation. Figure 1 shows a reply activity as the last node in the simple process. As Figure 2 shows, it sends the response for the start operation using Output1 as the output parameter. A reply activity doesn't necessarily need to be at the end of the process. A process could start with a receive activity, and then return a response before proceeding to do other work. You could have more than one reply activity for each receive activity, such as in the case where your process has multiple paths. The idea is that, when another component calls a request-response operation of a process's interface, it needs to eventually get a response for that operation (it could instead get a fault returned instead of a reply; we'll talk about that shortly).

Figure 2. Reply activity details
Reply activity details

Invoke activity

An invoke activity simply calls an operation on another service. The services you can call with an invoke activity depend on your processes' partners, which we will explain shortly.

The way you implement an invoke activity is shown in Figure 3, where the CallService invoke activity is defined to invoke the doService operation of the ServicePartner.

Figure 3. Details for an invoke activity
Details for an invoke activity

Structured activities

A structured activity contains other activities. The structured activities include:

  • Sequence
  • Choice
  • Receive choice
  • Parallel
  • While loop
  • Scope.

Sequence activity

The simplest structured activity is a sequence. A sequence activity contains other activities that run sequentially in the order in which they appear within the sequence. The activities it contains may be simple or they may be other structured activities. One thing we should point out: looking back at Figure 1, the complete process consists of a sequence of activities between the initial and final nodes. The editor canvas is actually one big sequence activity where you add more simple or complex activities. The sequence activity is hidden to keep the diagram clean. In fact, all the structured activities that follow, except for parallel, contain a hidden sequence wherever light-grey arrows connect activities.

Figure 4 shows a simple sequence activity containing two nodes. The CallFirst activity runs first followed by the CallSecond activity.

Figure 4. A sequence activity
A sequence activity

Choice activity

A choice structured activity (also known as a switch) controls which path the process takes, based on a condition. Simply put, a choice activity lets you decide the next set of activities that will run. A choice activity contains case elements that consist of an expression that evaluates to either true or false, followed by a sequence of activities. The first case element that evaluates to true wins, and its sequence of activities run next. A choice activity can also contain an otherwise element, which is the path that is taken when no case element evaluates to true.

Take Figure 5 for example, ShippingChoice is a choice activity and SmallOrder is a case element. SmallOrder has a condition that is expressed using a visual snippet. The condition specifies that if the quantity is greater than or equal to 1 and less than 10, then the return value will be true and the CourierOrder activity will run next. The fourth article describes in detail the visual snippet editor, which is what the example uses to define the condition for the SmallOrder case. Figure 5 also shows an Otherwise element, whose path will be taken when neither of the two case elements evaluate to true.

Figure 5. A choice activity and case condition
A choice activity and case condition

Receive choice activity

Related to both the choice and receive activities is the receive choice activity. A receive choice activity (also known as a pick) looks and works a lot like a choice activity. The difference is that in place of the case elements, there are one or more receive elements and no otherwise element. Each of the receive elements in a receive choice activity accepts a certain type of message (a particular operation of the process’s interface). When a process reaches a receive choice activity, execution stops and waits to receive a message. The difference between a plain receive activity and a receive choice activity is that, with a receive choice activity, any one of a number of operations could be received. The first operation the process receives wins, just like a plain choice activity, and the process follows its path.

Figure 6 shows an example of a receive choice activity called OrderAction. When OrderAction is reached, the process will stop and wait for a call to either the Proceed or the Cancel operation. If the Proceed operation is called first, then the ProcessOrder invoke activity will run, followed by the Update activity.

Figure 6. A receive choice activity
A receive choice activity

Parallel activity

Sometimes, you don't want all your activities to run in order, as they do in a sequence activity. When your process has groups of activities that can run concurrently, or the flow might branch to activities on other paths, you can place them in a parallel activity (also known as a flow). Activities inside a parallel activity can still run in sequential order by connecting them with links.

A link is directional that you can draw from a source activity to a target activity. When the source activity finishes running, the target activity at the other end of the link runs. You can create links from a single source activity to multiple target activities or multiple source activities to a single target activity. The only thing that you cannot do is to create a cycle, meaning the source activity links to the target activity which links back to the source (similar to an endless loop).

Links can have a link condition, which is an expression to control whether the link is allowed. If the link condition returns false, that means the link cannot be followed. In this case, if this is the only link between a source and a target activity, the target activity does not run. This situation gets a bit complicated when it comes to multiple incoming links.

Let’s imagine a situation where a target activity has many incoming links such as Activity4 in Figure 7. What would happen if some of the links are followed and some are not? By followed, we mean that the activity at the source of the link finished running and there was no link condition returning false. By default, the target activity runs when any one of the incoming links is followed. A join condition lets you specify when the target of one or more links should run. You can create a join condition using Java code, a visual snippet, or selecting from a list of simple choices.

If a join condition is not satisfied, then a join failure fault is thrown. You can tell the process not to throw a join failure fault, and instead, simply skip the activity and carry on to the next one, by selecting Yes for Suppress Join Failure on the Join Behavior tab of the activity’s properties.

That's a lot to digest, so this is probably a good time for an example. Figure 7 shows a parallel activity that contains four activities. After Activity1 completes, Activity3 runs, since there is no condition on the link between Activity1 and Activity3. Activity2 runs concurrently, but only if the amount value is less than 5 (as the link condition shows in the bottom of the figure). Figure 8 shows that the join condition for Activity4 is set to All, which means that Activity4 will run only when both of the incoming links are followed. However, if the link condidtion between Activity1 and Activity2 is false, then the link between Activity2 and Activity3 is never be followed. In this case, the join condition can never be satisfied and a join failure occurs.

Figure 7. A parallel activity
A parallel activity
Figure 8. A join condition
A join condition

While loop activity

When you want a group of activities to run multiple times, until some condition no longer holds true, you can use a while loop activity. A while loop activity contains other activities and a condition. When the condition evaluates to false, the loop terminates and the next activity after the while loop runs.

Let's look at a simple example. Figure 9 shows a while loop that stops iterating whenever the isComplete variable has a value of true (since the inverse node returns false ). Each time the loop iterates, it calls the CheckServiceComplete service, which returns a boolean value that is assigned to the isComplete variable. Thus, whenever the service returns true, the loop exits and the Reply activity runs.

Figure 9. A while loop activity
A while loop activity

Scope activity

A scope activity is a structured activity that can enclose any other activities. A scope activity lets you define local variables, local correlation sets, and various handlers. The activities within a scope have access to any variables that belong to that scope. A scope activity can contain more scope activities within it, so activities within a scope can also access variables of all enclosing scopes.

In the details for a scope, you can enable two options: isolated and compensable. When you choose isolated, access to variables is controlled so that, when simultaneous activities are running, only one can access the variables at a time. When you choose compensable, you can invoke compensation handlers for the scope.

We'll revisit scope activities when we discuss variables, correlation sets and each type of handler later in the article.

Fault activities

Inevitably, situations arise that prevent your process from reaching completion. A fault is an anticipated error that can occur. Fortunately, there are specialized activities to deal with these cases:

  • Throw
  • Rethrow
  • Compensate
  • Terminate.

Throw activity

A throw activity lets you signal that something has gone wrong in your process. If the operation was a request-response type and had a fault part along with the input and output parts of the interface, then a throw activity can signal an error condition to the caller of the operation. When you throw a fault with a throw activity, you might want to handle some problems as part of your processes instead of just returning a fault, in which case you can create a fault handler (more about fault handlers later, but you can probably guess what they do) to catch the fault thrown. A fault must have a name and it can optionally contain a variable that holds information related to the error.

Earlier in the choice activity section, we mentioned in the example that an OrderSizeFault would be thrown for order sizes that weren't in the range covered by each case element. Figure 10 shows the details for the ThrowOrderSizeFault activity.

Figure 10. Throw activity
Throw activity

Rethrow activity

A rethrow activity is the same as a throw activity, except that it occurs within a fault handler. It enables you to rethrow a fault that is caught by a fault handler so that any enclosing scopes or callers of the process can handle it. For example, the OrderSizeFault hander might log the exception, and then rethrow it so that the order processing component, who called the process, doesn’t proceed to bill the customer. We’ll explain this further in the fault handling section.

Compensate activity

A compensate activity lets you invoke a compensation operation for an activity or a compensation handler for a scope. You can only place it inside a compensation handler or fault handler. Compensation is an "undo" action for work that has already successfully completed. For example, suppose your process involves shipping orders after payment is received and an activity to accept payment from a customer has completed successfully. Then, something goes wrong and the complete order can't be shipped. A compensation handler might do something like reimburse the customer for the missing items. We'll talk more about compensation handlers shortly.

For a compensation activity, you set the target activity for the compensation, which is either a single activity or a scope, as Figure 11 shows.

Figure 11. A compensation activity
A invoke activity compensation

Terminate activity

A terminate activity lets you stop a process instance as soon as possible without performing any compensation or fault handling.

Utility activities

Some other useful activities include

  • Assign
  • Snippet
  • Human task
  • Wait
  • Empty.

Assign activity

An assign activity lets you copy values from one variable to another or to initialize variables. In the fourth article, you saw something similar when you assigned values to the inputs and copied values from the outputs of service calls within the business state machine. As an example of what an assign activity can do, suppose you want to update order information after shipping completes. Figure 12 shows how to copy the quantityShipped value from the shippedOrder business object to the quantity attribute of the order business object.

Figure 12. An assign activity
An assign activity

Snippet activity

When you need more complex logic for an activity than other activities can provide, you can use a snippet activity, which lets you delegate work to a small program that you create. You can choose plain Java™ to define what the snipped activity does, or you can use the visual snippet editor that we covered in the fourth article.

Human task activity

In the second and third articles, we introduced you to human task components. You can also include human tasks directly in a process. A human task activity is used when work is to be performed by a person.

Wait activity

You can use a wait activity when you need your process to stop running for some period of time. In the details for the activity, you can simply specify a duration to wait, or you can specify a specific time and date when the process should continue to run. You can even use the visual snippet editor to compute the duration to wait. Figure 13 shows a wait activity that will wait until December 1, 2006 at noon to call the EmailSeasonsGreetings service.

Figure 13. A wait activity
A wait activity

Empty activity

You might need an activity that does nothing at all, such as when you have a construct that requires an activity, but there is no work to be done. For example, as we will describe in the fault handling section, you might want to ignore certain faults and just carry on with your process. Since a fault handler must contain an activity, you can just insert an empty activity to suppress the fault. You can also use empty activities as place holders for activities whose details you'll fill in later.


Partners

A service component defines a set of interfaces that your process must implement. It may also define a set of references to other services that your process can call. Within a process, we use the term partner to describe the other services that may be calling your interfaces or that you may be calling. There will be one interface partner for each interface on the component for which your process belongs. Each reference of the component that the process implements corresponds to one reference partner within the process. Put very simply, when a client calls your process, you can think of it as an interface partner that called you. When you call another service, you will do so using a reference partner. So, an interface partner contains incoming operations and a reference partner the outgoing operations.

As an example, the component for the process in Figure 1 has an interface with the start, and continue operations (for the Start and Continue activities, respectively), and those operations belong to the SimpleProcess interface partner. Reference partners are what you use to call the other services, as you saw in Figure 3, where we defined the CallService invoke activity to invoke the doService operation of ServicePartner.

When you generate a process implementation for a component by right-clicking on a component in the assembly editor, and selecting Generate Implementation - Process, all the component references appear under Reference Partners and are available for service calls. Likewise, when you create a process first, then drag the process on to the Assembly editor, it creates component references for all the reference partners. This is just one of many ways that Websphere Integration Developer makes things a little bit easier when creating and connecting services. Of course, you can add more references and partners as needed after creating the component and process.


Variables

A variable is a container for business data that is used within a process (or any component type for that matter). You can declare variables by right-clicking in the Variables section of the process editor and selecting Add variable. We mentioned in the scope activity section that you can declare local variables within a scope. A local variable is one that is only available for use (that is, you can assign to it, or fetch its value) within the scope in which it is declared, and within nested scopes as well.

When you add a variable in the Variables section, you are adding it to the currently selected scope. For example, when you select different scopes, you will see the variables section change to display the variables that belong to each scope. A global variable, on the other hand, you can access anywhere within your process. To declare one, make sure no scope activities are selected when you add a variable. As we mentioned when we described receive activities, global variables are created automatically for the input and output parameters of the process's operations.

When you create a variable, you need to declare what type it is before you can use it. There are two kinds of variables: data type and interface. A data type variable is a business object or a simple type such as string or integer. An interface variable has a type based on an input or output message type in the WSDL interface file. If you look back at Figure 3, you'll see that Use Data Type Variables is checked. This enabled us to set the order business object as the variable.


Handlers

A handler is a set of activities that is associated with a particular activity or the process as a whole. A handler runs when certain situations occur. The types of handlers are:

  • Fault
  • Event
  • Compensation.

Fault handlers

When a problem or exceptional situation occurs while a process runs, you can use a fault handler to undo partial and unsuccessful work for the scope in which the fault occurred. A fault handler is an optional part of a scope or invoke activity. You create one by right-clicking on a scope or invoke activity and selecting Add Fault Handler. A fault handler is triggered when a fault is thrown by the runtime infrastructure, when a service is called, or when a throw activity runs.

A fault handler contains one or more catch elements. You can add one catch for each fault that could potentially occur within the scope or the activity. Each catch contains a sequence where you can add activities to do whatever work needs to be done for the particular fault. This is where you can use the compensate, rethrow, or empty activities, in addition to any other activity. You can also add a catch all element to deal with any faults that are not caught by any catch element.

As an example, Figure 15 shows a simple fault handler for the ShipOrder activity. Figure 14 shows the interface for the process that contains the handler. Normally, the process replies with the shippedOrder business object, but if the ShipOrder service (whose operation also has the invalidCustId fault) throws an invalidCustId fault, then the process replies with the invalidCustId fault instead.

Figure 14. Interface with fault
Interface with fault
Figure 15. A fault handler
A fault handler

Event handlers

We saw how to use receive and receive choice activities to accept calls made to a process. You probably wondered, "what if the process isn't stopped and waiting for a particular operation call?" This is exactly what event handlers are for. An event handler looks a lot like an exception handler, except that it starts running when an OnEvent element receives a call to the corresponding operation. An OnEvent element is equivalent to a receive activity, so you need a corresponding operation in one of the process's interfaces.

Another element you can add to an event handler is a timeout. A timeout is implemented in the same manner as a wait activity. The difference is that a timeout in an event handler works independently of the rest of the process.

You can add an event handler to any scope when a process is long running (as we will explain, long running means that the process is interruptible and can wait for external asynchronous inputs). An event handler starts running when the activity enters the scope and stops running when the activity exits the scope.

In Figure 16, if you call the cancelOrder operation on the OrderProcessing interface, and either the CheckInventory or the ShipOrder activities are running, then the terminate activity runs and the process ends.

Figure 16. An event handler
An event handler

Compensation handlers

As we mentioned when we talked about the compensate activity, compensation lets you undo a completed activity. You can add a compensation handler to an invoke or scope activity to take whatever steps are necessary to reverse the completed work. The scope or invoke activity defining the compensation handler must complete before the compensation handler can run. Therefore, if a scope or an invoke throws a fault, compensation for that activity cannot run since it never completed its work. Once the activity installs a compensation handler, you can invoke the handler using a compensate activity.

When a compensation handler runs, it is as though it is a continuation of the scope's execution. That is, you have access to the variables that were visible in the scope, and they will contain the same values as when the scope completed.

Figure 17 shows a compensation handler for the inner scope (whose name is CallAndNotifyScope), and contains the CorrectNotify activity. In the outer scope, a fault handler contains a compensate activity whose target is set to the inner scope. If something goes wrong after the inner scope has completed and the fault handler runs, then the CorrectNotify activity runs.

Figure 17. A compensation handler
A compensation handler

Correlation sets

Earlier in Figure 1, we showed a process that had two receive operations. One question you might ask is, "when there are multiple instances of a process running, how do you know which instance will receive the call to the second operation?" If you read the fourth article on business state machines, you'll remember that we had exactly the same problem when sending messages (calling operations) to multiple instances of running state machines. To solve the problem, state machines use a correlation set. Not surprisingly, the same concept applies to business processes (which, as we mentioned, provides the underlying implementation of a state machine).

A correlation set lets you specify which messages belong to which process instance. It consists of a property, on which correlation is based, and aliases for that property. An alias is a part of a message that represents the correlation property. For example, in Figure 18, which is the correlation set for the process in Figure 1, the activity uses the orderNum property to correlate the incoming requests. Figure 19 shows creating an alias (as a result of clicking New), which is the orderNumber attribute of the Order business object. In Figure 18, orderNumber correlates both start and continue operation calls. Note that for each alias, you could use different business objects. All that matters is that each alias has the same type, which in this case is int.

Figure 18. A correlation set
A correlation set
Figure 19. A correlation property alias
A correlation property alias

Once you have a correlation set, you need to specify which alias the application will use to initiate the correlation set. This means that the process instance that receives the value of that alias will be used when any of the aliases contain that same value. Figure 20 shows setting the correlation set to be initialized when the Start activity runs.

Figure 20. Using a correlation set
Using a correlation set

Let's look at how this works at runtime to make sense of all this. Suppose the application calls the start operation once and the value of orderNumber is 123. The process then calls start again with an orderNumber value of 124. Later, if the value of orderNumber contains 123 when the application calls continue, then the first process instance receives the call.

The property that is used for correlation could change as the process continues. For example, you might have a process that is correlated on a customer identifier when the process starts. Later, if the customer orders something, the rest of the process might need to be correlated on the order number. Notice in Figure 19 that we selected Input as the direction (hence the Direction in Figure 20 was set to Receive). You could also select Output to initiate another correlation set when a reply of an invoke activity is received.


Long running processes and microflows

There are two types of business processes: long running and microflows. A microflow is a business process that runs as a single transaction. A microflow is non-interruptible, which means that it cannot contain a wait or human task activity or more than one receive activity since each of these require the process to pause. It also can only have compensation on activities, not compensation handlers, since no state is preserved as the process runs.

A long running process, on the other hand, can stop running and all features are permitted. The state is preserved as the process runs. If you restart the server, the process will still be running and in the same state where it left off. Typically, components implemented as long running processes are called asynchronous, which means that a client would call them, and then proceed to do other work while it waits for a reply.


WS-BPEL Standard

One final thing to point out before you get back to work and build a business process: WebSphere Integration Developer supports the Business Process Execution Language for Web Services (BPEL4WS) Specification, but it also provides convenient enhancements. You can disable these extensions if you want to ensure your process can run on another BPEL-compliant server by checking Disable WebSphere Process Server BPEL Extensions when you use the New Business Process wizard. As a side note, in case you haven't discovered it, rather than right-clicking a component and selecting Generate Implementation, as we have shown you, you can also create implementations using a wizard.

Here's a list of some of the enhancements that are available:

  • Embedded human tasks
  • Java expressions and Java snippets
  • Microflows
  • Valid-from setting
  • Additional properties for each process element such as display name, description, and documentation.

Putting it all together

Let's have some fun and use what we learned to enhance the Order Processing application -- the one you put together in the third article. We implemented the ShippingProcess component with a trivial business process: it just makes a call to the ShippingTask service, and then notifies the ProcessOrder component that the ShippingTask service shipped the order. Let's build on that and implement it with more complex logic in the process. We also included the complete application (orderprocessingcompleteprocess.zip.) as a download if you just want to skip ahead and browse the complete business process.

Suppose your boss tells you that it is possible that not all items in an order will be shipped at once. If an item is out of stock, the company policy is to ship what is available, and then ship the rest whenever the stock is replenished. If it turns out, however, that it will be more than five days until the item to be shipped will be restocked, then the process completes and notifies the customer that it did not ship all of the items.

Importing the project

First, let's import the project that we built in the third article. To save you some time and let you concentrate on just the new business process, the latest version of the module has the necessary additional interfaces and business objects already added, so be sure to start with the project in the orderprocessingemptyprocess.zip file.

  1. Download the orderprocessingemptyprocess.zip file from the Downloads section.
  2. Click File => Import => Project Interchange, and then click Next.
  3. Click Browse next to the From zip file field. Browse to the orderprocessingemptyprocess.zip file that you just downloaded, and click Open. This zip file is the Project Interchange file.
  4. Check OrderProcessing, and then click Finish. The OrderProcessing module opens in the Business Integration view and, as the project builds, you see a "Building workspace" message in the lower right corner of the workbench. Wait for building to complete.
  5. Expand the OrderProcessing module and then double-click OrderProcessing to open the assembly editor.
  6. Double-click the ShippingProcess component in the Assembly editor to open the business process editor. Figure 21 shows the business process that you will enhance.
Figure 21. The ShippingProcess business process
The ShippingProcess busines process

Let's quickly recap what we have in Figure 21. The business process adheres to the Shipping interface. You can double-click the Shipping interface in the Business Integration view to open it in the interface editor to browse it. You'll see that it has one operation, shipOrder, which takes an order business object as input. So, the fact that we used this interface means that a call to the shipOrder operation of the Shipping service invokes the process. The data contained within the Order object will be available for use within the process.

Because the ShippingOrder component was wired to the ProcessOrder and ShippingTask components, the generation of the process implementation created two reference partners: ProcessOrderPartner and ShippingTaskPartner respectively. As you might recall from the third article, you will use these to make service calls to those components.

Based on the rules specified earlier, you need to have the process continue trying to ship items for the order until either all items are shipped, or until the restocking time is too long to wait. You can use a WhileLoop activity for this. The loop needs to determine when to exit, so in the next steps, you will also create the shippingComplete variable which, when set to true, will cause the loop to exit. Feel free to review the section on the visual snippet editor in the fourth article before you proceed, since we won't elaborate on the steps we take to create the visual loop condition.

Creating and initializing variables

Before we get to that though, we need some global variables to use throughout the process. Let's create them in the next steps:

  1. Right-click in the Variables section and select Add Variable, and then change the name to shippingComplete.
  2. In the Details section of the Properties view for the new variable, ensure Data Type is checked, click Browse, and then select boolean from the list of types.
  3. In the same manner, create a shippingFault variable with the ShippingFault type.

Just a note about that last step: in the original OrderProcessing module, the ShippingTask service returned an Order business object, but that business object doesn't contain some information that you need for the proposed changes, namely the quantity shipped or restocking information. Therefore, in the new version of the application you downloaded, there is a new ShippedOrder business object that contains the quantityShipped and restockDays attributes. We also changed the interface for the ShippingTask component to return this new business object.

Next, you need to initialize some of the variables that the process uses later.

  1. Right-click the ShippingTask activity, and then select Insert Before => Assign. Change the name to Initialize.
  2. In the From list in the details for the Initialize activity, select Fixed Value, and then type false for the value.
  3. In the To list, select Variable, and then select shippingComplete as Figure 22 shows.
Figure 22. The Initialize assign activity details
The Initialize assign activity details

You have just specified that the shippingComplete variable has a value of false immediately after the process moves past the Receive activity.

Creating a While loop

Now we can get to the loop part of the process:

  1. Right-click the ShippingTask activity and select Insert Before => While Loop. Rename it to LoopUntilShipped.
  2. In the Details section of the Properties view for the loop, click Create a New Condition.
  3. Drag the shippingComplete variable from the Variables section of the visual snippet editor to the canvas.
  4. Right-click the editor and select Add => Standard, select inverse under the logic category, click OK, and then click the editor canvas.
  5. Delete the false node since it isn't needed.
  6. Connect the shippingComplete node to the inverse node, and the inverse node to the return node so that your loop condition is the same as Figure 23.
  7. Save the business process editor
Figure 23. A loop condition
Loop condition

Your process should now look as in Figure 23. You might want to look ahead to Figure 29 to see what the final process looks like to help keep things in perspective. You need the inverse node because you want the loop to exit when shippingComplete is true, but the loop needs a value of false for the loop to terminate. The red 'x' in LoopUntilShipped occurs because there are no activities within the loop. This is an error because you now have an infinite loop. After all, with no logic inside the loop, there is no way for shippedOrder to be set to true.

Implementing logic within the loop

The next steps begin to fill in the logic within the loop, which is to invoke the ShippingTask service and then determine whether to wait and try again. Since we have already covered visual snippets in two of the previous articles, we will not bore you with very detailed steps to create snippets any more.

  1. Drag the ShippingTask activity inside the LoopUntilShipped activity.
  2. Right-click within the LoopUntilShipped activity, select Add => Snippet, and then rename it to CalcTotalShipped.
  3. Fill in the visual snippet logic as in Figure 24. The add node is under the math category of the standard visual snippets.
Figure 24. Calculating the amount shipped
Calculating the amount shipped

You now have an activity to do the shipping work. The value returned by the ShippingTask activity contains the number of items ShippingTask shipped, so the snippet will increment the quantityShipped variable. You will use that variable to make the decision of what to do next following the steps that create the choice activity:

  1. Right-click again within the loop activity, select Add => Choice, and then rename it to DetermineNextAction.
  2. Right-click the DetermineNextAction activity, select Add => Case, right-click again and select Add => Otherwise.
  3. In the Description tab of the properties for the first Case, type NotEnoughShipped, and then, in the Details tab, click Create a New Condition. This opens the visual snippet editor.
  4. Fill in the snippet logic as in Figure 25. The and node is under the logic category of the standard visual snippets.
  5. In the same manner, rename the second case to EnoughShipped, and then fill in the snippet logic as in Figure 26.
Figure 25. The NotEnoughShipped case
The NotEnoughShipped case
Figure 26. The EnoughShipped case
The EnoughShipped case

The logic for the first case element is to return true if not enough items were shipped and the number of days left for the items to be restocked is less than five. The other case element of the loop handles where the full order was shipped. There's no condition to define for the Otherwise element, since it is the path that will be taken if the first two cases do not evaluate to true.

The next step is to create some activities for each case. In fact, if you have saved the process, you will see a red ‘x' next to the NotEnoughShipped case because at least one activity is expected. The next steps fill in the activities for each path that your logic can take in the choice activity.

If the NotEnoughShipped case is true, then we want to wait a while, and then try shipping the rest of the items again. For this, we need to add a wait activity. To ship the rest of the items, we just need to let the loop iterate again, since the activity that calls to the shipping component is at the start of the loop.

  1. Right-click the NotEnoughShipped case element and select Add => Wait.
  2. In the Details section of the Properties view, select Java for the expression language and then select Duration.
  3. Change the value 0 to 10 in the created expression. This value is the number of seconds to wait.

When the wait activity is reached, the process stops running for ten seconds, and then, since there are no further activities after the wait, and since the shippingComplete variable is still false, the next iteration of the loop occurs. When all the items have shipped, we want to exit the loop. To do this, we simply set shippingComplete to true. Let's fill in the case when enough items are shipped:

  1. Right-click the EnoughShipped case element, select Add => Assign, and then change the name to SetShippingComplete.
  2. In the same manner as the Initialize activity earlier, set the shippingComplete variable to true.

The only case that is left, when the first two cases are false, is that more items were shipped than were ordered, or not enough were shipped, but the restocking time is too long. This is a problem, so we need to throw a fault here. To keep things simple, we will just report that a problem occurred.

  1. Add another assign under the Otherwise element and rename it to SetErrorMsg.
  2. In the details for the assign activity, set the From list to Fixed Value and type "Shipping problem" (including the quotes) for the fixed value.
  3. Set the To list to Variable and select shippingFault => message.
  4. Click New at the bottom-left of the assignment details, then create another assignment of the fixed value of true to the shippingComplete variable. (Assignment activities can have multiple assignments.)
  5. Add a throw activity under the SetErrorMsg activity.
  6. In the throw activity details, select User-defined for the fault type, leave the default namespace, and set the fault name to shippingFault.
  7. For the fault variable, click Browse and select shippingFault from the list.

Defining a fault handler

The next step is to define the fault handler to catch the shippingFault:

  1. Right-click the LoopUntilShipped activity, and then select Insert Before => Scope.
  2. Left-click the LoopUntilShipped activity, and then drag it into the scope activity.
  3. Right-click the scope activity and select Add Fault Handler.
  4. In the details for the Catch element in the fault handler, select User-defined for the fault type. Note that clicking the orange and red 'x' at the top-right of the scope activity toggles between showing and hiding the fault handler.
  5. Type ShippingFault for the Fault Name and then type shippingFault for the Variable.
  6. Browse to ShippingFault for the data type.
  7. Under the ShippingFault element in the fault handler, add a snippet activity, and then fill in the details as in Figure 27.
Figure 27. Fault snippet contents
Fault snippet contents

Notifying the client that the order shipped

The last step is to notify the client that the order shipped with the updated order values (the quantity shipped will now contain the amount that was actually shipped). The NotifyShipped activity is already in place as the last activity of the process to do just that. Your process should now look like the one in Figure 28.

Figure 28. The complete shipping process
Fault snippet contents

Testing the component

Let's quickly test the component now. If you are familiar with running the entire module as the third article showed you, you can try running that. We'll just quickly show you the steps to test the ShippingProcess component here.

  1. Right-click on the ShippingProcess component in the OrderProcessing assembly editor and select Test Component.
  2. In the test client that opens, enter 1 for orderNumber, 10 for quantityOrdered, leave quantityShipped as 0 and enter any values for productID and customerID.
  3. Click Continue. Select a server when the deployment location dialog opens and click Finish.
  4. When the test client for the ShippingTask component receives the emulate event (since you selected to test one component in the module, the rest will be emulated by default), enter 9 for quantityShipped and 3 for restockDays.
  5. Click Continue.

This data satisfies the NotEnoughShipped case and thus causes the Wait activity to run. Ten seconds later, the loop runs again.

  1. When the ShippingTask component receives the emulate event again, enter 1 for quantityShipped, leave restockDays at 0, and then click Continue.
  2. When the ProcessOrder component receives the emulate event, just click Continue.
Figure 29. Testing the business process
Testing the business process

The process has now completed. It has shipped the customer their ten items and notified the ProcessOrder component.


Conclusion

Business processes are a key part of your business integration application. You can use them to the define steps of your business logic, to coordinate and choreograph other services, and to involve people. Business processes can execute their activities in sequence or in parallel, over a very short period of time, or a much longer duration spanning days, weeks or longer. This article and the previous article on business state machines showed you two important ways to define your application logic.


Downloads

DescriptionNameSize
OrderProcessing - incomplete business processorderprocessingemptyprocess.zip  ( HTTP | FTP )95 KB
OrderProcessing - complete business processorderprocessingcompleteprocess.zip  ( HTTP | FTP )97 KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Business process management on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Business process management, WebSphere, SOA and web services
ArticleID=148589
ArticleTitle= IBM WebSphere Developer Technical Journal : A guided tour of WebSphere Integration Developer -- Part 5
publish-date=07262006