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.
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.
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 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
startoperation, 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
CallServiceactivity runs and, when it finishes, the process stops running until it receives a call to thecontinueoperation. -
Once a call is made to the
continueoperation, the process continues to thePrepareResponseactivity.
Figure 1. 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
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
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
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
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
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
Figure 8. 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
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.
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
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
Terminate activity
A terminate activity lets you stop a process instance as soon as possible without performing any compensation or fault handling.
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
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
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.
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.
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.
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.
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
Figure 15. A fault handler
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
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
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
Figure 19. 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
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.
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.
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.
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.
-
Download the
orderprocessingemptyprocess.zipfile from the Downloads section. - Click File => Import => Project Interchange, and then click Next.
-
Click Browse next to the From zip file field.
Browse to the
orderprocessingemptyprocess.zipfile that you just downloaded, and click Open. This zip file is the Project Interchange file. - 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.
- Expand the OrderProcessing module and then double-click OrderProcessing to open the assembly editor.
- 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
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:
-
Right-click in the Variables section and select
Add Variable, and then change the name to
shippingComplete. - 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.
-
In the same manner, create a
shippingFaultvariable 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.
-
Right-click the ShippingTask activity, and then
select Insert Before => Assign. Change the name to
Initialize. -
In the From list in the details for the Initialize
activity, select Fixed Value,
and then type
falsefor the value. - In the To list, select Variable, and then select shippingComplete as Figure 22 shows.
Figure 22. 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.
Now we can get to the loop part of the process:
-
Right-click the ShippingTask activity and select
Insert Before => While Loop. Rename it to
LoopUntilShipped. - In the Details section of the Properties view for the loop, click Create a New Condition.
- Drag the shippingComplete variable from the Variables section of the visual snippet editor to the canvas.
- Right-click the editor and select Add => Standard, select inverse under the logic category, click OK, and then click the editor canvas.
- Delete the false node since it isn't needed.
- 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.
- Save the business process editor
Figure 23. A 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.
- Drag the ShippingTask activity inside the LoopUntilShipped activity.
-
Right-click within the LoopUntilShipped
activity, select Add => Snippet, and then rename
it to
CalcTotalShipped. -
Fill in the visual snippet logic as in Figure 24. The
addnode is under the math category of the standard visual snippets.
Figure 24. 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:
-
Right-click again within the loop activity,
select Add => Choice, and then rename it to
DetermineNextAction. - Right-click the DetermineNextAction activity, select Add => Case, right-click again and select Add => Otherwise.
-
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. -
Fill in the snippet logic as in Figure 25. The
andnode is under the logic category of the standard visual snippets. -
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
Figure 26. 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.
- Right-click the NotEnoughShipped case element and select Add => Wait.
- In the Details section of the Properties view, select Java for the expression language and then select Duration.
-
Change the value
0to10in 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:
-
Right-click the EnoughShipped case
element, select Add => Assign, and then change
the name to
SetShippingComplete. -
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.
-
Add another assign under the Otherwise element
and rename it to
SetErrorMsg. -
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. - Set the To list to Variable and select shippingFault => message.
-
Click New at the bottom-left of the assignment
details, then create another assignment of the fixed
value of
trueto the shippingComplete variable. (Assignment activities can have multiple assignments.) - Add a throw activity under the SetErrorMsg activity.
-
In the throw activity details, select User-defined for the
fault type, leave the default namespace, and set
the fault name to
shippingFault. - For the fault variable, click Browse and select shippingFault from the list.
The next step is to define the fault handler to catch
the shippingFault:
- Right-click the LoopUntilShipped activity, and then select Insert Before => Scope.
- Left-click the LoopUntilShipped activity, and then drag it into the scope activity.
- Right-click the scope activity and select Add Fault Handler.
- 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.
-
Type
ShippingFaultfor the Fault Name and then typeshippingFaultfor the Variable. - Browse to ShippingFault for the data type.
- 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
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
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.
- Right-click on the ShippingProcess component in the OrderProcessing assembly editor and select Test Component.
-
In the test client that opens, enter
1for orderNumber,10for quantityOrdered, leave quantityShipped as0and enter any values for productID and customerID. - Click Continue. Select a server when the deployment location dialog opens and click Finish.
-
When the test client for the
ShippingTaskcomponent receives the emulate event (since you selected to test one component in the module, the rest will be emulated by default), enter9for quantityShipped and3for restockDays. - Click Continue.
This data satisfies the NotEnoughShipped case and thus causes the
Wait activity to run. Ten seconds later, the loop
runs again.
-
When the
ShippingTaskcomponent receives the emulate event again, enter1for quantityShipped, leave restockDays at0, and then click Continue. -
When the
ProcessOrdercomponent receives the emulate event, just click Continue.
Figure 29. Testing the business process
The process has now completed. It has shipped the customer their ten items and notified the ProcessOrder component.
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.
| Description | Name | Size | Download method |
|---|---|---|---|
| OrderProcessing - incomplete business process | orderprocessingemptyprocess.zip | 95 KB | FTP |
| OrderProcessing - complete business process | orderprocessingcompleteprocess.zip | 97 KB | FTP |
Information about download methods
Learn
-
Business Process Execution Language for Web Services
version 1.1
-
Business Process with BPEL4WS: Understanding BPEL4WS
-
WebSphere Integration Developer product information
-
WebSphere Process Server product information
-
WebSphere Process Server: IBM's new foundation for
SOA
-
Build a Hello World SOA application
-
Service Component Architecture
-
Common Event Infrastructure
Get products and technologies
Discuss

Richard 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 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 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 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.
Comments (Undergoing maintenance)





