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

Unleashing visual snippets and business state machines in your service-oriented application

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.

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

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



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

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



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

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



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

Photo of Jane Fung 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.



21 June 2006

Also available in Chinese

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
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
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
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
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
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
Dialog box for adding a Java snippet

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
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
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
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
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
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:

  1. Identify a property that will be present in all operations.
  2. 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
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
The OrderProcessing module

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.

To get things ready to run, start WebSphere Integration Developer with a new workspace and import the downloaded file using the following steps:

  1. Download the orderprocessing.zip file in the Downloads section.
  2. Select File - Import - Project Interchange, and then click Next.
  3. 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.
  4. 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:

  1. After the workspace finishes building, expand SimpleOrderProcessing in the Business Integration view and drill down to Business Logic - State Machines - ProcessOrder.
  2. To open the business state machine editor for the ProcessOrder component, double-click ProcessOrder.
  3. 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
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:

  1. To open the assembly editor, double-click SimpleOrderProcessing in the SimpleOrderProcessing project.

  2. Right-click the ProcessOrder component, and click Test Component.

  3. 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
    Setting the input for the placeOrder operation
  4. To start the test, click Continue.

  5. When the Deployment Location dialog opens, ensure WebSphere Process Server v6.0 is selected

  6. 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
    Setting the input for the placeOrder operation
  7. 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:

  1. When the test client stops at the manual emulation event for the CustomerInformationPartner, type true for the Output parameter.
  2. 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:

  1. 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.
  2. When you are prompted to switch to the debug perspective, click Yes.
  3. 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
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.

  1. 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.
  2. Switch back to the test client, and click the Invoke icon Invoke icon.
  3. 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.
  4. 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

DescriptionNameSize
Project interchange fileorderprocessing.zip  ( HTTP | FTP )24 KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

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

 


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

All information submitted is secure.

Choose your display name



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

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

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

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

 


All information submitted is secure.

Dig deeper into Business process management on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Business process management, WebSphere
ArticleID=128467
ArticleTitle= IBM WebSphere Developer Technical Journal : A guided tour of WebSphere Integration Developer -- Part 4
publish-date=06212006