 | Level: Intermediate Randy Giffen (Randy_Giffen@ca.ibm.com), Advisory Software Developer, IBM Richard Gregory (gregoryr@ca.ibm.com), Staff Software Developer, IBM Greg Adams (Greg_Adams@ca.ibm.com), Distinguished Engineer, IBM Jane Fung (jcyfung@ca.ibm.com), Advisory Software Developer, IBM
21 Jun 2006
This is the fourth in a series of articles exploring a
service-oriented approach to application integration using
IBM® WebSphere® Integration Developer. In the third article,
you learned how to apply the concepts covered in the first
two articles by building a simple application. In this
article, you will learn more about business state machines
and the visual snippet editor.
From the IBM WebSphere Developer Technical Journal.
Introduction
A
previous article
in this series had you build a simple service-oriented
order processing application using WebSphere Integration
Developer. You saw how its concepts and tools worked
together to construct the building blocks of the
application. You implemented one of the components,
ProcessOrder, with a business state machine, but we gave
you only minimal background information about what you
were doing as you were building it. We chose a state
machine to implement that component because, for each
order, the steps that were taken to process the order
depended on the current state of the order.
In general,
a state machine is useful when your component's
activities are event driven and each activity that
occurs depends on the current state of the component.
Event driven in this case means that the component waits for
calls to its operations to know when it should take the
next step. It's time for us to dive in and explain each
state machine concept to help you understand what is
available for building bigger and more robust state
machines of your own.
Before we dive in to the state machine concepts, we'll
take a quick look at the visual snippet editor. In
business state machines, as well as in business
processes, you'll sometimes need custom logic.
For example, before your process can determine whether
it should continue down a particular path, or to help
your state machine determine which state transition to
make, you often need to compute some
business data. Because users of WebSphere Integration
Developer are not required to have detailed knowledge of
any programming language, the visual snippet editor
plays an important role in this situation.
While you build your applications, you will probably
want to test various parts to make sure they are working
as you expect before you continue. You saw in the last
article how easy it is to test your applications, even
before parts of them are ready to go. You also know from
experience that the first time you run something,
problems are likely to pop up. So, we'll let you run the
order processing application again, but this time we'll
show you how easy it is to debug your components. We'll
also show you some more tricks on testing state machines
with the test client.
In the sections that follow, you will learn about each of the following:
-
The visual snippet editor and all its features.
-
All the parts of a business state machine.
-
How to debug a state machine (or any component, for that matter).
The visual snippet editor
If you tried the example in the previous article, then
you have already worked with the visual snippet editor.
As with business state machines, we didn't spend much
time exploring the editor, so let's look in more detail
at how the editor helps you develop your
applications.
Whether you are creating a BPEL process, a business
state machine, or any of several other types of
components, you need to define custom expressions and
behavior. In most cases, you are required to express
this using Java™. But what if you don't know the details
of writing Java code? Or maybe you know Java coding, but you don't
know the details of the methods that are available to
use in this context.
WebSphere Integration Developer provides
a visual snippet editor for defining custom
behavior without having to write Java programs. The visual
snippet editor uses a graphical view that lets you
work at a conceptual level without knowing the details
of how to express logic in textual Java code. For
example, Figure 1 shows a visual snippet that prints
information to the Java console. Notice that, to get to
the customerID, you don't need to know the printing
syntax of Java, nor how to access the attributes of the
Order business object. The figure shows a list of all
the attributes of the myOrder variable that are
available. The snippet appends the customerID of the
myOrder variable to the string Shipping order to, and
then prints it to the Java console.
Figure 1. A simple visual snippet
Visual snippet nodes
The general purpose of the visual snippet editor is to
add nodes to a diagram to perform the required work. The
simplest diagram would consist of a single node. You can
add more than one node to a diagram. The relative
positions of the nodes are important because nodes are
executed in order from top to bottom.
When nodes execute, they often compute a value. A
terminal on the right side of the node represents the
resulting value. Looking back at Figure 1, you can think
of the computed value of the append text node as the
value (a string) consisting of customerID appended to
the string, Shipping order to.
Similarly, nodes might
require certain values in order to execute. You supply these values
by connecting result terminals to input
terminals. You can extend this pattern to create an
entire group of connected nodes. For example, the value
computed by the append text node is then passed to the
print to log node as input because we connected the append text terminal to it.
For the most part, you can divide the available set of
nodes into three types: expressions, snippets, and
control structures:
- An expression node contains a
texual expression.
- A snippet node computes a value or
performs some task.
- A control structure node causes
branching or looping within your visual snippet logic.
Expression nodes support simple expressions involving
arithmetic and boolean (true or false logic) operators.
They also support a dotted notation to drill into values
in a data structure. For example, when we selected the customerID
attribute of the myOrder variable from the
list in Figure 1, the expression displayed as
myOrder.customerID. Had customerID been a business
object as well (that is, containing it's own
attributes), then it could have been further expanded in
the same manner.
Figure 2 shows some examples of other expressions. In
the first example, the variable total is incremented by
2.5 times newvalue. In the second example, the variable ok is
assigned a value of true if both the checked and safe variables are true;
otherwise it is assigned a value of false.
Figure 2. A simple expression showing variable assignment
As mentioned, expression nodes also support simple
arithmetic and logical expressions. One of the simplest
expressions identifies a variable only (or a field of a
variable, if the variable is a business object, and not
just a simple type). In this case, the expression has
both an input terminal and a result terminal. A value
that is connected to the input terminal of such an
expression represents assignment of the value to the
variable or field. The input value can be a simple
expression or be a value computed by another node.
Figure 2 shows two examples of this.
Variables in snippets
There are two types of variables in the visual snippet
editor: local and global. A local variable is a variable
that is only available for use within the snippet in
which it is declared. You can declare a local variable
simply by creating an expression containing only the
name of the variable, and assigning a value to it. The
value you assign determines the variable's type, which
might be a Java or BO type. For example, Figure 3
shows a local variable called status that has a type of
string, because a string is assigned as its value. The
variable is then used as input to the append text node.
A global variable, on the other hand, is available to be
used in any snippet within the same component. The list of
variables in the business state machine or process
editor contains global variables. Therefore, because it
is a local variable, the status variable will not display in the list
of global variables for use in other snippets within a
business state machine. To create a global variable,
right-click in the Variables section of the Business
Process editor or the business state machine editor, and
click Add Variable.
Figure 3. An example of declaring a local variable in a snippet
Snippets as reusable pieces of code
Put simply, snippets represent and produce executable
code. Standard visual snippets are available in a
library that organizes them into categories, as Figure 4
shows. Looking back at Figure 3, you can see the use of
the append text standard visual snippet.
Figure 4. Selecting a standard visual snippet
In most cases, the existing standard visual snippets
likely will supply all the required general-purpose
functionality. For cases where they do not, you can
select any Java method, constructor, or field to use in
a snippet. Figure 5 shows the dialog box in which you
can select a visual snippet; in this case, the
endsWith method of the Java string class.
Figure 5. Dialog box for adding a Java snippet
Figure 6 shows using the endsWith snippet to check if
the msg variable is equal to the some value
string, and then storing the result (true or false) in the
isSomeValue variable. In the dialog box in Figure 5, you
can also select other visual snippets (or any Java code,
for that matter) that you have created yourself and that
specify custom behavior.
Figure 6. Example of using Java snippets
Complex visual snippet constructs
A visual snippet diagram also supports the conditional
execution of code groups, which you create by adding a
conditional control structure. This structure requires a
Boolean input. If the input value is true, the code
groups in the upper part of the control structure
execute. Otherwise, the code groups in the lower part of
the structure execute. For example, in Figure 7,
found prints if list contains 234DF, and
missing prints if it does not.
Figure 7. Example of using a conditional control structure
For even fancier snippets, you can use control
structures that support looping. For example, the for --
each control structure takes a
collection or array as input, and then repeats the groups
that are contained within it for each item in the input.
Using this control structure, you could calculate a
total for every item in an order list, as we show in
Figure 8.
Figure 8. Example of using the looping control structure
We have summarized each feature of the visual snippet
editor. Now we can move on to business state machines,
which is one typical place where you will use visual
snippets.
Business state machines
We mentioned in the previous article that a business
state machine is a special type of business process. So,
the question is, when do you use a state machine, as
opposed to a business process? Well, if a process
involves responding to events, and the response depends
on the current state of the process, then it might be
useful to implement the process as a business state
machine.
The term state machine might sound technical,
but it is based on a very simple and well-understood
design. The state machine in WebSphere Integration
Developer is similar to the state machine defined in
UML2. The idea is that the process will always be in
only one of any number of particular states. How the
state machine responds to a given event depends on the
current state of the state machine.
State machine components and interfaces
As with most WebSphere Integration Developer components,
authoring a business state machine means defining both
its interface (or interfaces) and its implementation.
Together, these interfaces define the set of operations
to which the state machine will respond; in SOA terms,
this is the set of operations provided by the service and
implemented by the state machine component. However,
remember that not all operations may be valid for the
current state. For example, consider the state machine
in Figure 9. You can only call the placeOrder operation
to begin the process, and you can only call orderShipped
when it is in the OrderBeingShipped state. If a client
using your state machine service calls the wrong
operation for the current state, the client will receive
a fault to let it know what happened.
Figure 9. A simple business state machine
The operations that make up an interface of a state machine may be of either the one-way or request-response type.You use the
request to send a message to the state machine
to trigger a state transition. The response does not
return any data unless you set it in an action (see the
next section), but it is possible that a fault will be
returned, such as when you call the wrong operation for
the current state. So, you need to have at least one
fault as part of the operation.
The data supplied with
each request operation sent to a business state machine
must carry enough information to identify which state
machine instance should be the recipient of the data.
After all, there could be thousands of instances running
at the same time; one for each of your customers. The
data supplied with each request operation is known as
correlation data, and is required for all state
machines, as we will explain shortly.
States
An instance of a business state machine can be in only
one state at any given time. For each state, there can
be an action associated with state entry and exit. These
actions occur whenever the state is entered or exited,
respectively. Composite states are states that contain
other states. Three special types of states are the
initial state, the final state, and the terminate state.
As you might guess, the initial state is the state in
which a state machine starts. A final state is used to
identify normal or expected state machine completion,
while a terminate state should be used to identify
abnormal or unexpected completion.
Transitioning from one state to another
The state machine's initial state must have a single
outgoing transition. This transition must have an
associated operation known as the initialization
operation, as Figure 10 shows. When this operation is
called and the transition occurs, then a new instance of
the state machine is created. This instance exists until
the machine reaches a final or terminate state. All
other transitions from one state to another may have
operations that, when called, cause a transition to the
next state. You can also have transitions that trigger
automatically when the source state is entered, or
because of a timeout, or
transitions that do not have a triggering operation.
Figure 10. Initial state with initialization operation
You can also associate a condition (known as a guard) with the transition.
The guard must evaluate to true in order for the
transition to proceed. You can have more than
one transition from a state associated with the same
operation (or with no operation); however, in this case,
each transition must have a guard. A guard is a piece of
code (visual or textual Java) or a service invocation
that belongs to a transition that returns either true or
false. When a state change is about to occur, the guard
that returns true determines the transition that occurs. It is
up to you to ensure that only one of these guards
evaluates to true, and remember that there is no guarantee which guard
will be evaluated first. Figure 11 shows the guards for
the transitions out of the CustomerBeingChecked state.
The Good Customer guard returned the value of the
isCustomerOK variable (which was set to either true or
false while in the CustomerBeingChecked state), and the
Bad Customer guard returned the inverse.
Figure 11. Transitions with associated conditions
When a transition occurs, it can trigger an
action that is associated with the transition. Figure 11 also shows Print Info actions along
with the guards. You can implement such actions using
visual or textual Java code, or as an invocation of an
SCA service. Note that both the condition and action on
a transition can access parts of the message
belonging to the triggering operation.
For example,
suppose an Order business object was the input of the
operation that triggered a transition. Then, you can
directly access the Order object in the action that is part of that
transition. If you want to use Order elsewhere in the
state machine, such as in a later state, you can assign
the value of Order to a global variable. You can also
use an action to assign values to the parts of the
message that are used for the reply of the operation
(the output part of the interface).
The destination state of a transition can be the same as
its source state. This is refered to as a
self-transition. In the state machine editor,
you can mark self-transitions as internal in the
properties for the transition. This means that state
entry and exit actions will not be triggered by the
transition.
You can trigger transitions originating from a composite state
regardless of which state within the composite
state is the current state. A composite state can also
have a default transition with no operation. When the
machine reaches a final state within a composite state,
it triggers the default transition automatically.
Correlation of state machine instances
As we mentioned, you must specify the correlation
information for every operation of the state machine's
interfaces. You do this in two steps:
- Identify a property that will be present in all
operations.
- Identify, for each operation, the part that will be used to supply the
value for the property.
To make that a little clearer,
Figure 12 shows the OrderNumber property that has an int
type. Each operation (message) that is part of the state
machine's interface has one part that is specified as an
alias of the OrderNumber property. This means that when you call
either the placeOrder or orderShipped operation, the value of the orderNumber attribute of the
Order business object (which is obtained as part of the
input parameter) determines which state
machine instance will be used.
Figure 12. Associating a message part with a correlation property
Testing and debugging visual components
Let's run and test the application again, but this time
we'll "debug" our application. There isn't anything
wrong with the application, at least not that we know
of, but if there were, it would be helpful to know how
to track down where things are going wrong. In case you
don't have the module from
article 3 in your workspace,
we have provided it at the end of this article for you
to download. Keep in mind that the testing and debugging
we do here are useful for any type of component, not
just business state machines.
First, let's recap the application, so that you
understand what is happening as it runs. As Figure 13
shows, the order processing application
(OrderProcessing) receives order information from an
external client. It then checks whether the client is in
good standing (and ideally fabulously wealthy) and, if
so, forwards the order to the shipping department. When
the shipping department confirms that the order has been
shipped, the application prints a message.
Figure 13. The OrderProcessing module
To get things ready to run, start WebSphere Integration
Developer with a new workspace and import the
downloaded file using the following steps:
 | |
Tip: When you start WebSphere Integration
Developer, you have the option to select an
existing workspace or to create a new one. You can
also chose to always use the selected workspace and
not be prompted again at start up. If you have
chosen to not be prompted for the workspace to use,
but you later need to choose or create a new
workspace, you can do so by navigating to Window -
Preferences - General - Startup and Shutdown and then
unchecking Prompt for workspace on startup.
|
|
-
Download the orderprocessing.zip file in the
Downloads section.
-
Select File - Import - Project Interchange,
and then click Next.
-
Click Browse next to the From zip file field.
Browse to the orderprocessing.zip file that you
just downloaded, and click Open. This zip file
is the Project Interchange file.
-
Check SimpleOrderProcessing, and then click
Finish. The SimpleOrderProcessing 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.
A project interchange file is a zip file containing
authored artifacts for a set of modules. By authored
artifacts, we mean the pieces that you created for your
application, such as components and business objects.
This is in contrast to the generated artifacts such as
Java class files. The project interchange file contains
enough information for WebSphere Integration Developer
to recreate each module in your workspace. It is useful
for sharing modules between developers who do not have
access to a common source code repository or versioning
system. You can also export any of your modules as
project interchange files using the following steps:
-
After the workspace finishes building, expand
SimpleOrderProcessing in the Business
Integration view and drill down to Business
Logic - State Machines - ProcessOrder.
-
To open the business state machine editor for
the ProcessOrder component, double-click
ProcessOrder.
-
Right-click the OrderBeingShipped state, and
then click Debug - Add Entry Breakpoint.
As Figure 14 shows, a blue dot shows in the upper right
corner of the OrderBeingShipped component. This means
that, when this state is entered, the state machine
stops running. You are then able to inspect, and even
change, the variable contents as they exist at that
point. While stopped at a breakpoint, you can also
inspect the execution stack. The stack
contains a trace of each component that has been called
to that point.
Figure 14. Setting a breakpoint in a state machine
We just want to hit our breakpoint in the state machine,
so we're not interested in executing the other
components. Here is a handy trick for when you are
developing components and they aren't quite ready for
testing, but you do want to test other components in
your module: any time you select Test Component(s) in
the assembly editor, the unselected components (in this
case all but the ProcessOrder component) will be
emulated. As you might recall from
article 3, emulating
means that, instead of calling a service for a
component, the test client displays the input that was
sent to the service and prompts you to enter the output.
You can also define an emulator that will execute
automatically, and you can even get fancy and add some
logic to the emulator to return, for example, different
values based on the input.
There is another interesting side to emulating all the
references of your state machine. If you recall from
article 3, when the placeOrder operation was called, the
orderShipped operation was eventually called to trigger
the transition to the OrderComplete state. However, this
time, that won't happen. Because you will be emulating
the Shipping component, that component will not be able
to make the expected call to the orderShipped operation.
The emulator doesn't know what the component that it's
emulating is supposed to do, so there's no way for it
make any service calls. So, it seems at first glance
that you're stuck forever in the OrderBeingShipped state
when you test this way. Well, all you need to do is use
the test client again to do the orderShipped service
call for you. We'll show you the correct way to do that
after we pass our breakpoint.
Now that we have set a breakpoint, let's make it pop by
following these steps:
To open the assembly editor, double-click
SimpleOrderProcessing in the
SimpleOrderProcessing project.
Right-click the ProcessOrder component, and
click Test Component.
For the operation, select placeOrder, and
then fill in some values, as shown in Figure 15.
Figure 15. Setting the input for the placeOrder operation
To start the test, click Continue.
When the Deployment Location dialog opens, ensure
WebSphere Process Server v6.0 is selected
Select Debug for the mode, as Figure 16 shows.
This is important, because, if the mode is set to Run,
your breakpoints will be ignored.
Figure 16. Selecting the deployment location
Click Finish.
It doesn't matter what values you use for the input,
with the exception of orderNumber. Recall that the calls
to the ProcessOrder state machine are correlated on the
orderNumber, so the value you enter is important: the
same value must be used when the other ProcessOrder
operations are called, as we will see when we use the
test client to send an orderShipped message.
The state machine starts in the WaitingForOrder state
and then the call you just made to the placeOrder
operation causes a transition to the
CustomerBeingChecked state. There is an action on the
state entry to check the customer information by calling
the CustomerInformationPartner. The return value from
the CustomerInformation service is saved in the
isCustomerOK variable. However, because we didn't select
to test that component, it will be emulated, and it will
be the value that you enter in the emulator that is
stored in isCustomerOK. The following steps explain how
to do that:
-
When the test client stops at the manual
emulation event for the
CustomerInformationPartner, type
true for the
Output parameter.
- To return the value, click Continue.
The transitions from the CustomerBeingChecked state are
both automatic (there is no operation that triggers
either of them), and the transition that occurs depends
on the value of isCustomerOK, which will just have been
set to true after the emulator completes. The transition
to the OrderBeingShipped state occurs and, just as the
OrderBeingShipped state is entered, two things occur:
A call is made to the Shipping service,
which you are also emulating, and your
breakpoint pops (meaning that execution stops at that
point). The following steps show how to inspect the
variables at this point:
-
When the test client stops at the next manual
emulation event (this happens as the state is
entered along with the breakpoint being hit, and
so it might happen just before, or just after,
the breakpoint pops), click Continue. There is
no return value to enter; in some upcoming steps
we'll tell you how to trigger the next state change.
-
When you are prompted to switch to the debug
perspective, click Yes.
-
In the Variables view, expand both
placeOrder_Input_order and isCustomerOK.
Now you can see the values of your state machine's
variables while you are in the OrderBeingShipped state,
as Figure 17 shows. Notice that the blue breakpoint
symbol is highlighted with yellow to indicate that it
has popped. The values that you entered as the operation
input for the Order business object display in the
variables view, as is the value that you set in your
emulator that was saved in the isCustomerOK variable.
There are also some internal variable values showing;
you generally don't need to be concerned with those.
If there were many component calls before your
breakpoint was hit, you would see the call stack in the
Debug view. There was only a service call within one
component at this point, so in Figure 17, you see only
one item in the stack, ProcessOrder.OrderBeingShipped.
Figure 17. Inspecting variables while in the OrderBeingShipped state
As we discussed earlier, when you let the state machine
continue past the breakpoint, it stays in the
OrderBeingShipped state until the orderShipped operation
is called. The next set of steps show you how to use the
test client to trigger the transition to the
OrderComplete state. Remember, you need to let the state
machine know which running instance that you are
sending the message to. Therefore, you need to make sure
you use the same correlation ID as when you called the
placeOrder operation. The value of orderNumber in the
Order business object, which is used as input for both
operations, has been set as the correlation ID.
-
Right-click ProcessOrder.OrderBeingShipped in
the Debug view, and select Resume. The state
machine is running again and waiting for a call
to orderShipped. Remember that if the second manual
emulation event occurred after the breakpoint was
reached, you still need to click Continue
in the test client.
-
Switch back to the test client, and click the
Invoke icon
.
-
For the operation, select orderShipped. Enter
15 for orderNumber, and enter any values for the
rest of the input to the operation. You also entered
the value of 15 for the placeOrder operation,
which is used as the correlation ID to
ensure that the call is made to the correct
instance.
- Click Continue.
The state machine now transitions to the OrderComplete
state, and that instance is complete. You should see,
Order has been shipped and Order is complete printed in the console.
Summary
In this article, you learned how to use business state
machines to implement components using WebSphere
Integration Developer. You also saw how to use the
visual snippet editor to add more detailed logic to a
state machine. Then you saw how to test and debug an
application, including some fine points of testing a
state machine. Stay tuned for the next article where you
will learn about implementing a component using business
processes.
Download | Description | Name | Size | Download method |
|---|
| Project interchange file | orderprocessing.zip | 24 KB | FTP | HTTP |
|---|
Resources Learn
Get products and technologies
Discuss
About the authors  | 
|  |
Randy Giffen is an advisory software developer at the
IBM Ottawa Lab on the WebSphere Integration Developer
team. 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.
|
 | 
|  |
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.
|
 | 
|  | 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. |
 | 
|  | Jane Fung is an Advisory Software Developer at IBM Canada
Ltd, where she is responsible for developing the Business
Process Execution Language (BPEL) and Business Rules
debuggers in WebSphere Integration Developer. Prior to
that, she was the team lead of the WebSphere Studio
Technical Support team.
|
Rate this page
|  |