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
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
newvalue. In the second example, the variable
assigned a value of true if both the
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
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
msg variable is equal to the
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
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
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. 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
to begin the process, and you can only call
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.
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
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.
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
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
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:
- 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 workspacemessage 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
It doesn't matter what values you use for the input,
with the exception of
orderNumber. Recall that the calls
ProcessOrder state machine are correlated on the
orderNumber, so the value you enter is important: the
same value must be used when the other
operations are called, as we will see when we use the
test client to send an
The state machine starts in the
and then the call you just made to the
operation causes a transition to the
CustomerBeingChecked state. There is an action on the
state entry to check the customer information by calling
CustomerInformationPartner. The return value from
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
isCustomerOK. The following steps explain how
to do that:
When the test client stops at the manual
emulation event for the
truefor 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
OrderBeingShipped state occurs and, just as the
OrderBeingShipped state is entered, two things occur:
A call is made to the
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
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
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,
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
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
15for orderNumber, and enter any values for the rest of the input to the operation. You also entered the value of 15 for the
placeOrderoperation, 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
state, and that instance is complete. You should see,
Order has been shipped and
Order is complete printed in the console.
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.
|Project interchange file||orderprocessing.zip ( HTTP | FTP )||24 KB|
- A guided tour of WebSphere Integration Developer -- Part 1: Get a driver's view of the WebSphere Integration Developer landscape
- A guided tour of WebSphere Integration Developer -- Part 2: SOA development with WebSphere Integration Developer
- A guided tour of WebSphere Integration Developer -- Part 3: Building a simple service-oriented application
- Web Services and Web Service Description Language
- Service Component Archtitecture Series
- Tuscany Service Component Architecture
- developerWorks: WebSphere Process Server and WebSphere Integration Developer resources
- WebSphere Integration Developer product information
- developerWorks: WebSphere Business Integration zone
- developerWorks: WebSphere development tools zone
- Meet the experts: WebSphere Integration Developer