The previous article in this series covered the basic concepts of WebSphere Integration Developer and its suite of tools. In that article, we also saw the main steps to building an order processing application (OrderProcessing) using a service-oriented architecture. At this point, you probably wish you had read that last article, or perhaps you read it, but had not consumed enough coffee to remember the details. Fear not, we'll do a quick recap to set the stage before diving into the details of how to implement the services of our application.
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, a message is printed.
To implement this application, we need a business object representing the order information. The business objects are sometimes referred to as the currency of the application, because all of the services use them. Speaking of services, we will also need services to receive the order, check the customer information, and ship the order. These services are represented by the three dark blue boxes in Figure 1.
Figure 1. A simple order processing application
In the previous article, you learned that we could define each of our services and wire them together without actually knowing the implementation details of any of the services. To do that, we created a module (OrderProcessing Module), and then created each of the services. Next, we identified the interfaces that each service would support, and each interface from another service that that they planned to call. Finally, we wired the services together based on which service had to call which other service. This approach is extremely useful because it allows us to lay out an entire application, top-down, without having to worry about the implementation of each service until the entire architecture is designed. In fact, we can have one user lay out the overall service-oriented architecture, and a team of people each implementing one of the services based on the contract (interfaces) that the architect specified.
What will you learn?
Now that we have refreshed our brains on the basic structure of our order processing application, it is time to roll up our sleeves and build it.
In the sections that follow, you will learn how to do:
- Create a module to hold all the artifacts that you will be authoring.
- Create a business object to represent a customer order.
- Create components and their interfaces.
- Wire together the components.
- Specify the implementations of these components.
- Deploy and test what you have built in the WebSphere test environment.
Creating the OrderProcessing module project
To begin constructing the application, we need a project to hold the business objects, components, and interfaces. The type of project we will create is a service assembly module project, or module project for short. This is a special type of project that is aware of the different types of artifacts (business objects, components, and so on.) and can be deployed and run on the WebSphere Process Server.
The module project corresponds to the large outer blue box in Figure 1. Notice that all of the components, interfaces, and wires are contained inside the large blue box, and hence will be contained inside our new module project.
Enough chit chat, let's actually do it!
- Ensure that the Business Integration perspective is open.
- Right-click the Business Integration view and select New > Module.
- In the New Module wizard, enter
OrderProcessingfor the Module name.
- Click Finish.
WebSphere Integration Developer creates a project named OrderProcessing, as shown in Figure 2. You might remember (or maybe not) the different types of components discussed in the previous article in this series. The Business Integration view categorizes your components based on their type: process components, state machine components, and so on. Similarly, it categorizes your resources by type: your business objects are under Data Types and the interfaces for each component are under Interfaces. The category-based structure of the Business Integration view makes it easy to find artifacts of a specific type. The Business Integration view also provides several other options for sorting and navigating your artifacts.
Figure 2. The OrderProcessing project
Creating the Order business object type
In this section, we'll create a business object to hold the order information. The Order business object will be passed between the components as they perform our business logic. The Order business object will contain the following attributes:
- Order number,
- Product ID,
- Quantity being ordered
- Identifier of the customer who placed the order
The product ID and customer ID can contain alphanumeric data and, therefore, will have a string type. The order number and quantity will have an int type because they will contain only integers.
To create the Order business object, follow these steps:
- Right-click the Data Types category in the OrderProcessing project, and select New > Business Object.
- In the New Business Object wizard, enter
Orderin the Name field, leave the defaults for the rest of the fields, and click Finish.
Now that we have our business object, it is time to create some attributes to hold the order information. Creating attributes is quick and easy:
- Ensure that the Order business object is selected in the Business Object editor. It gets selected by default when we created the business object.
- To create our four attributes, right-click the Order object and select Add Attribute. Repeat that three more times.
- Select attribute1, which is the first default name, and
replace it with
orderNumber. Click the default string type and select int from the types list.
- Rename attribute2 to
quantityand change its type to int.
- Rename attribute3 to
productIDand leave string as the type.
- Rename attribute4 to
customerIDand leave string as the type.
- Save your changes.
Before closing the editor, let's take a closer look at it. The top portion of the editor (see Figure 3) displays the main elements of the business object. We can use this area to edit common properties of the business object, including the name and type of each attribute. The editor uses the Properties view to show more advanced properties of the business object and its attributes. For example, we can only restrict the set of allowable values for an attribute in the Properties view.
Figure 3. The completed Order business object type
When you are finished enjoying the fine selection of properties afforded by the Properties view, close the Order business object editor.
Before we move on, take a quick peek at the Business Integration view (typically in the top left corner of the workbench). You should be able to see the new Order business object under the Data Types category. Our application now has its currency.
Creating the components and interfaces
It's time to create our components (services) and define the interfaces that they will support as well as other component's interfaces that they will call. We will implement the following components and interfaces:
- ProcessOrder component and interface
- CustomerCheck component and interface
- ShippingProcess component and interface
- ShippingTask component and interface
- CustomerInformation import
- OrderProcessing export
The ProcessOrder component
We start by creating our OrderProcessing component (see Figure 1) to receive the order and begin working on it.
- In the Business Integration view, open the assembly editor by double-clicking OrderProcessing under the OrderProcessing project.
- Right-click the assembly editor and select Add Node - Component (with no implementation type).
- Right-click the component that we just created and select
Rename. Change the name Component1 to
Figure 4 shows the completed ProcessOrder component. The warning symbol is displayed because there is no implementation for the component yet. Don't panic, we don't know exactly how we will implement the component, nor should we care. We are still trying to sort out the pieces of our application and identify what they will do in the grand scheme of the application universe.
Figure 4. The ProcessOrder component
At this point, you need to ask yourself, "Alright, what does this component need to be able to do?" As we described in the application overview, the ProcessOrder component places an order based on the order information that it receives. When the order has been shipped, the component prints out a message. This means that we have to be able to tell this component to place an order, and we have to be able to let it know the order has been shipped. Capturing this requirement is easy; we simply need to create an interface for the component and identify the two operations that it will support.
The ProcessOrder interface
The ProcessOrder interface has two operations, placeOrder and orderShipped. Both operations take an Order business object as input. There is no value returned from placeOrder because we only need it to kick off the ordering. Similarly, the orderShipped operation does not return any values because it only needs to print out a message when it is told that the order has shipped.
To create the interface for the ProcessOrder component, follow these steps:
- Right-click the Interfaces category in the OrderProcessing project and click New - Interface
- In the New Interface wizard, enter
ProcessOrderfor the name, and leave the other default values.
- Click Finish.
- In the interface editor that opens, right-click and select Add One Way Operation.
- Select the default operation1 name and replace it with
- Right-click the placeOrder operation and select Add Input.
- Change the name input1 to
order, then click the Type cell where it says string. As Figure 5 shows, a type list opens, including the Order type that you created earlier. Select Order for the type.
Figure 5. Creating the ProcessOrder interface
- Add another one-way operation, and then change the name
- Add an input to the orderShipped operation, rename it to
order, and then select Order for the type.
In the preceding steps, we chose One Way Operation. There are two operation choices; one-way and request-response. A one-way operation corresponds to when you don't expect your service to return a result. Request-response is when you want a two-way communication with the service, such as when you need to send a query and get information back, or when you want to send a message to kick off an action, but you need a response to know if it was successful.
Now you can give the ProcessOrder component its interface:
- Switch back to the assembly diagram, right-click the ProcessOrder component, and select Add - Interface
- Select ProcessOrder from the list of interfaces.
We now have our first component specified. Notice that we still have not actually implemented it; we have only identified what it will do for us. Let's move on to the next component.
The CustomerCheck component and interface
The next component that we'll create is CustomerCheck. This component's job is to receive the customer ID and confirm that the customer is in good standing. That means that when we define its interface, it will need an operation called checkCustomer. We will need that operation to return information about whether the customer is in good standing. Follow these steps to create CustomerCheck:
- Switch back to the assembly diagram and create the CustomerCheck component in the same manner as the ProcessOrder component.
- Create a new interface by repeating steps 1 to 3 in the previous
section where we created the OrderProcessing interface, and name it
Now that you have the interface, let's add our operation to check the customer standing:
- In the interface editor, right-click and select Add Request Response Operation.
- Change the name from operation1 to
- Add an input, change the name to
customerID, and leave the type as string.
Notice that we did not pass the entire Order to this component. That's because the component only needs to be aware of the customer ID to check the customer's standing. Let's make sure the operation returns whether the customer is in good standing:
- Add an output by right-clicking and selecting Add Output.
Change the name to
customerOKand select boolean for the type.
- Switch back to the assembly diagram, and add the CustomerCheck interface to the CustomerCheck component in the same manner as when you added the interface to the ProcessOrder component.
Figure 6 shows the completed CustomerCheck interface.
Figure 6. The completed CustomerCheck interface
Since the ProcessOrder component uses the service that CustomerCheck provides, we need to wire ProcessOrder to CustomerCheck.
- Use your mouse to hover over the edge of the ProcessOrder component. A yellow handle displays. Click the handle and drag it to the CustomerCheck component.
- You will be prompted to create a matching reference on the source node (ProcessOrder). Click OK, and then select CustomerCheck for the interface in the Add Reference dialog box.
Recall that when a component makes a service call to other components, it does so using a reference. In the last step, a reference was created automatically for you.
The ShippingProcess component and interface
The next component to create is ShippingProcess, which provides another service that the ProcessOrder component needs. This component is responsible for coordinating the shipping of the order and notifying the shipping department to assign a specialized shipping droid to the order. To accomplish this, we need the ShippingProcess component to support an interface with an operation that handles shipping the order.
- Create a component named ShippingProcess in the same manner as the previous ones.
- Use your mouse to hover over the edge of the ProcessOrder component and drag the handle to the ShippingProcess component that you just created. When the prompt asks you to create a matching reference, click OK.
- You haven't created the interface for the ShippingProcess component yet, so instead of selecting an existing interface, click New in the Add Reference dialog.
- In the New Interface wizard that opens, enter
Shippingfor the name and click Finish. This closes the wizard and brings you back to the Add Reference dialog.
- The Shipping interface that you just created is selected by default in the Add Reference dialog, so just click OK.
Time to catch our breath and see what we just did--the steps sure didn't seem like the previous component!
Well, we created our new component and immediately wired an existing component to it. WebSphere Integration Developer very helpfully made a new reference and interface on the fly for you. You didn't have to first run off and make the interface; instead, WebSphere Integration Developer made an empty interface for you, so you could continue your work and then come back and fill in the interface later.
Let's do that now. The Shipping interface needs a one-way operation, shipOrder, which takes an Order business object as input. The operation sends a message to the Shipping department component so that the shipping department knows to send the order.
To create the operation, follow these steps:
- In the Business Integration view, under the Interfaces category, double-click the Shipping interface. This opens the Shipping interface in the interface editor.
- Add a one-way operation named
- Add an input named
order, with the type set to Order. Figure 7 shows the completed Shipping interface.
Figure 7. The shipping interface
- When the shipping process completes, it needs to send a message back
to the OrderProcessing component to notify it that the order is
complete. Therefore, you need another wire from ShippingProcess back
to the ProcessOrder component.
Connect the ShippingProcess component to the ProcessOrder component and click OK to create the reference.
That's all there is to it because ProcessOrder already has an interface.
The ShippingTask component and interface
Next, we'll create the ShippingTask component and its interface. ShippingTask provides a service for the ShippingProcess component to call when it wants to create a task that a human must complete (or in our case, a specialized shipping droid).
The ShippingTask interface needs one request response operation, shipOrder, which takes an Order business object as input. The operation is used to send the order data to someone (the friendly droid) in the shipping department who will ship the order. The order data is returned from the ShippingTask. In the future, we might want to have the shipping task modify the order before returning it, perhaps to indicate the quantity that was actually shipped.
To create the human task component and its interface, follow these steps:
- Create another component called
- Connect the ShippingProcess component to the
ShippingTask component, click New to create an
interface, and then name it
- Click Finish in the New Interface wizard, and then click OK in the Add Reference dialog.
- Open the ShippingTask interface and add a request response operation
- Add an input named
order, with the type set to Order.
- Add an output named
completedOrder, also with its type set to Order.
Figure 8 shows the completed Shipping interface.
Figure 8. The ShippingTask interface
Hopefully by now you are getting the idea that laying out the service-oriented architecture of your application is pretty quick and easy. It's a matter of dragging your services (components) to the canvas, defining what you want them to do, and connecting the boxes together. You can probably do it with one arm tied behind your back, and without coffee!
The CustomerInformation import and OrderProcessing export
The main parts of the OrderProcessing module are now complete. All that is left is to connect it to the outside world. In this section, we will show you how to add an import and an export to do just that.
- The import will allow the CustomerCheck component to use the services of an external customer information system.
- The export will allow an external client to send the order information to the ProcessOrder component.
The CheckCustomer component needs to call an external information system, which contains all of our customer data. To connect to an external system, we must use an import. An import indicates that instead of calling another component in the module, we will be calling something that is outside our immediate application--something that we are trying to integrate with the overall service-oriented integration solution.
Recall from the second article that an import contains a binding that points to the actual external implementation. Perform the following steps to create the import. Then, in the implementation section of this article, you will create a binding.
- In the assembly editor canvas, right-click the canvas and click Add Node > Import.
- Change the name to
- Right-click the CustomerInformation import, click Add Interface, then select CustomerCheck from the list of interfaces (you created it with the CustomerCheck component).
- Connect the CustomerCheck component to the CustomerInformation import.
Before we move on, it's worth noting that we used the same interface for CustomerCheck and CustomerInformation. This is because CustomerCheck will receive the customer ID, do some business logic, and then call the external system with the same ID and the same type of operation--namely to check if the customer is valid. We could also have used different interfaces for the component and the import--but for simplicity in this article, we have opted to make use of the same interface.
As discussed in the second article, an import must be bound to another module, Web Service, Java™ Message Service(JMS) destination, or EJB component. Using the integration test client, you can still test the module even without defining the import binding. Therefore, for simplicity, you can omit selecting a binding.
To create the export, you need to do the following step:
- Right-click the ProcessOrder component and click Export - SCA Binding.
This step creates an export for your component, allowing it to be called from an external source. The binding you choose depends on how you plan to access the component. An example of using an export can be found in Building SOA solutions with the Service Component Architecture -- Part 1, which describes invoking a component using a JSP.
Your completed assembly should look similar to that shown in Figure 9. The application skeleton is now complete. Next, you will define the implementation for each component.
Figure 9. The completed OrderProcessing assembly
Implementing the ProcessOrder component
Although we've laid out the component topology, we've not yet said how any of the components will be implemented. Getting started with an implementation is simple; you just select a component and pick an implementation type for it. WebSphere Integration Developer will create a skeleton implementation and your job is simply to fill in the business logic.
We've decided to implement the ProcessOrder component with a business state machine. A business state machine is a special type of business process because it is event driven, and its actions depend on the current state of the process. In our case, we will use it to model the state of the order as it progresses from arriving, to shipping, to shipped.
- Right-click the ProcessOrder component in the assembly editor and click Generate Implementation - State Machine.
- A dialog opens asking in which folder the state machine should be placed. Ensure OrderProcessing is selected and click OK.
The State Machine editor opens with a trivial state machine. As Figure 10 shows, there is an error marker on the transition from the initial state to the first state because there is not yet an operation to trigger the transition. In other words, we need to identify the operation that gets the state machine rolling.
Figure 10. The newly created ProcessOrder businesss state machine
Notice the references on the right: these were added automatically when the state machine was created, based on the references you added to the ProcessOrder component. You will use those to make calls to other services.
First, we will rename the initial and final states to something more appropriate.
- In the State Machine editor, click the default name of State1,
and replace it with
- In the same manner, change InitialState1 to
- Rename FinalState1 to
Now let's add some more states to help us keep track of when we are checking the customer and when we are busy shipping the order.
- Right-click the canvas and click Add > State, then click the canvas to add the new state.
- Rename State2 to
- Right-click the CustomerBeingChecked state and select Add - Transition.
- When the line displays under the cursor, click the OrderBeingShipped state. This creates a new transition from CustomerBeingChecked to OrderBeingShipped.
- In the same manner, add a transition from the OrderBeingShipped state to the final state.
Your state machine should now look similar to the one shown in Figure 11, depending on where you put each state. The easiest way to think of this is to keep in mind that the state machine is literally trying to model the states that your application is going through as it processes the order. The application is either waiting for an order, checking the customer, shipping the order, or the order is completed.
Figure 11. The ProcessOrder component states
In the next set of steps, we define the triggers for the transitions between the states. First, we set up the transition that occurs when we are told the order has been shipped:
- Right-click the transition between OrderBeingShipped and OrderComplete and select Add Operation.
- Right-click again on the same transition and select Show in Properties.
- In the Properties view that opens, select ProcessOrder in the Interface list, and then select orderShipped in the Operation list. This means that when the orderShipped operation of the ProcessOrder component is invoked, it triggers the transition between OrderBeingShipped and OrderComplete.
- Next stop on the transition tour is to handle when we receive notification that an order needs to be handled. With the Properties view still open, select the WaitingForOrder to CustomerBeingChecked transition, select ProcessOrder in the Interface list, and select placeOrder for the operation.
There are two transitions coming from CustomerBeingChecked. One transition will be associated with a customer in good standing, in which case we can ship the order. The other transition will be for the customers we find to be somewhat undesirable. In that case, we want to wrap up the order and bid the customer a nice day.
A transition does not have to occur based on the state machine component receiving a message. Transitions can also happen automatically based on other criteria. In this case, we will base the transitions on the customer's standing.
- You first need a variable to hold the result of the customer information check (that is, the customer standing). Right-click the Variables section to the right of the state machine editor and click Add Variable.
- In the Data Type Selection dialog that opens, enter
isCustomerOKfor the variable name, and select boolean from the list of types.
Next, we'll define the transition for a customer in good standing whose order we will ship. To help you to write your action, WebSphere Integration Developer includes a visual snippet editor. Let's use that to write our code for filling our order and ID variables, and for printing some information to the log.
- Make sure the Properties view is still open (if it isn't, click the Properties view at the bottom of the workbench), and select the CustomerBeingChecked to OrderBeingShipped transition.
- By default, the transition type is set to Automatic, which is what you want. Click the Condition tab of the Properties view, and then click Create.
- In the visual editor that opens, click the isCustomerOK variable on the right and drag it onto the editor canvas.
- Right-click the canvas and click Add - Return, and then click the canvas again.
- Right-click the isCustomerOK variable on the canvas, select Add - Link, and then click the return expression.
- Change the name of the condition from Condition1 to
Good Customerand save the editor contents.
These steps create an expression that returns true or false for the condition depending on the value of isCustomerOK. When the condition evaluates to true, the transition will occur. Note that there will be an error marker indicating that "the transition will not occur because another transition will always occur." We'll fix that next.
The next set of steps deal with customers in bad standing and remedy the error marker.
- Select the transition between CustomerBeingChecked and OrderComplete, then right-click and select Add - Condition. Ensure the Details tab of the Properties view is open.
- Repeat steps 3 to 6 in the preceding list, except this time change
the condition name to
Bad Customer. This creates the same expression as the Good Customer condition.
- Click the Invert Result check box, because you want this transition to fire whenever isCustomerOK is false (that is, the opposite case to the Good Customer condition).
Now you have all the states and transitions in place. The next step is to define the actions that are supposed to happen in each state. The information you need to process an order is contained in the input to the placeOrder operation.
You need to store the order information in a variable so that you can pass it to the services that are called as the state machine processes an order. You will also need to store the customer ID that the order contains in another variable, so that you can pass it to the customer check component.
The next steps will create and assign values to those variables along with a logging statement so you can see what is occurring as the machine runs.
- Add another variable by right-clicking the Variables section and
selecting Add Variable. Enter
myOrderfor the name, and select Order as the type.
- Create one more variable called
myCustomerIDwith string as the type.
Now we need to create the actions on our transitions and make use of those variables.
- Right-click the transition between WaitingForOrder to CustomerBeingChecked and select Add - Action. This action lets you define what happens when the transition occurs (which is a result of calling the placeOrder operation).
- Change the name in the Properties view to
Print info and set variables.
We'll use the visual snippet editor again to define the action:
- To begin defining the action, click the Details tab.
- Right-click the canvas and select Add - Expression, and then click the canvas.
- In the expression box, enter the text
"Order has been placed. Setting Variables."(including the quotes).
- Right-click the canvas and select Add - Standard, and then select Utility - Print to log.
- Click the canvas, and then connect the string expression to the log expression by right-clicking the text expression, selecting Add - Link, and then clicking the Print to log utility.
- Drag the placeOrder_Input_order variable to the canvas (this will contain the input that is received when the placeOrder operation is called).
- Drag the placeOrder_Input_order variable, and then click at the end of the variable name, which displays a list. In the list, expand placeOrder_Input_order and select customerID.
- Drag the myOrder variable to the canvas, and then connect placeOrder_Input_order to it. This assigns the order data received to the myOrder variable.
- Drag the myCustomerID variable to the canvas, and then connect placeOrder_Input_order.customerID to it.
The details should now look as in Figure 12.
Figure 12. The Print info and set variables action
The next step is to call the service that checks the customer information when the order enters the CustomerBeingChecked state. To do that, we will use one of the references that was automatically created for us. Remember that this is a reference to the other component. We will use the variables that we created earlier.
- Right-click the CustomerBeingChecked state and select Add - Entry.
- Change the entry name to
Check Customer. In the Details tab of the Properties view, click Invoke . Click Yes when the message comes up informing you that you will lose any changes.
- Select CustomerCheckPartner from the Reference list. This reference was created when you created the wire from the ProcessOrder component to the CustomerCheck component.
- Select the checkCustomer operation from the Operation list. This is the only operation in the CheckCustomer interface.
- In the Variables box, select myCustomerID, and in the Operation Input box, select customerID
- Click Set. You have just specified that the input to the checkCustomer operation comes from the myCustomerID variable.
- To assign the return value of the service, which is a boolean value, to isCustomerOK, click the Output parameter button, then click both customerOK in the Operation output box and isCustomerOK in the Variables box. Click Set.
The entry for the state should now look like Figure 13.
Figure 13. Service call in the entry for the CustomerBeingChecked state
The next step is to add the service call to the shipping component when in the OrderBeingShipped state. The steps are the same as those for creating the entry action for the CustomerBeingChecked state:
- In the same manner as the previous steps, right-click on the
OrderBeingShipped state, select Add - Entry, change
the name to
Ship Order, then select Invoke for the implementation. Click Yes when the message informs you that you will lose any changes.
- For the Reference and Operation, select ShippingPartner and shipOrder respectively.
- For the shipOrder input, select myOrder and shipOrder in the Variables and Operation input lists respectively, and then click Set. The operation is one-way, so there is no output to set.
You may have noticed that as you were building the state machine that
there was one error all along:
Correlation set must
have at least one property.
When deployed to a server, your state machine could have several
instances, each in a different state. When an operation is called on the
ProcessOrder component, you need a way to make the call on the correct
instance. This is accomplished using correlation sets. A
correlation set tells the state machine which running instance to use for
the given input data. It does this by examining the contents of the input
data, using a specified field as a kind of key that uniquely identifies
the corresponding process instance.
In the OrderProcessing state machine, the order number will determine which instance to use. Correlation sets will be covered in more detail in a future article covering business processes.
- Click anywhere on an empty area of the state machine editor canvas, select Show in Properties and select the Correlation tab.
- Click New and, in the Edit Correlation Property dialog that
OrderNumberfor the name.
- Click Browse and select int for the type.
- Click New next to Aliases. This opens the Property Alias Selection dialog.
- At the bottom of the dialog expand placeOrder input, drill down to orderNumber, select it, and then click Add.
- Click New again and expand orderShipped input, drill down to orderNumber, select it, then click OK.
- Click OK to complete the correlation set.
You have just indicated that the orderNumber attribute of any Order business object used as input to either operation is an alias for the OrderNumber correlation. This means that the orderNumber contained within the Order business object will determine which instance of the state machine will receive the placeOrder message.
That completes the ProcessOrder component. For simplicity, we did not include error handling for cases such as an invalid operation called for the current state. You can just add a few more print statements so that when you test the application, you can see what is occurring as the state machine executes:
- Right-click the Bad Customer transition, select Add -
Action, and then change the name to
- In the property Details tab, right-click the canvas, select Add -
Expression, and then drop a new expression on the canvas. In
the expression box, enter
"Order has been rejected."(including quotes).
- Right-click the canvas again and select Add - Standard, and then select Utility - Print to log.
- Click the canvas, and connect the string expression to the log expression.
- Repeat the previous steps to create another action named
Print Infofor the orderShipped transition that prints
"Order has been shipped."and for the Good Customer transition that prints
"Order will be shipped."
- Add one last entry action named
Print Infoto the OrderComplete state that prints
"Order is complete."
The completed ProcessOrder state machine should now look similar to the one in Figure 14.
Figure 14. The Completed OrderProcessing business state machine
Implementing the ShippingProcess component
The next component to implement is ShippingProcess. You will implement it using a business process that invokes the ShippingTask component, and then calls the orderShipped operation on the OrderProcessing component to indicate that the order has been shipped. Business processes will be covered in detail in a future article in this series.
- Open the OrderProcessing assembly editor, and then right-click the ShippingProcess component and select Generate Implementation... - Process.
- When the dialog box opens and asks where to put the process implementation, click OK to accept the default. The business process editor opens, as shown in Figure 15..
Figure 15. The ShippingProcess business process
Often when creating a business process, you might find it helpful to lay out the structure of all of the activities but not worry about their details (just as it is when you create your module assembly diagram). After you have the activities you can then loop back and fill in more details. Let's try that approach now by creating a couple of activities that will wake up the shipping droid and then notify the process order component when shipping is complete.
- Right-click the canvas and select Add - Invoke, and then
change the name of the Invoke activity to
- Repeat this to add a second invoke named
Let's go back to the two activities we just created and fill in some details.
- Select the ShippingTask activity and open the Details tab in the Properties view.
- Click Browse next to Partner and select ShippingTaskPartner.
- As with the state machine, the partners available depend on the
references in the assembly diagram; there is one partner for each
reference. There is only one operation for the ShippingTask operation,
so it will appear in the Operation list.
Ensure that the Use Data Type Variables check box is selected, and then, for both the Input and Output variables, click the selection button to the right of each variable and select Order for the variable.
- In the same manner, select the NotifyShipped activity, browse to ProcessOrderPartner in the property details, and select the orderShipped operation. Also, set the variable to Order.
The completed ShippingProcess is shown in Figure 16.
Figure 16. The completed ShippingProcess implementation
Now, when the shipOrder operation is called, it sends a message to someone in the shipping department to ship the order by calling the shipOrder operation of the ShippingTask component. When the task is complete, the NotifyShipped activity will call the orderShipped operation on the ProcessOrder component, which will trigger a transition to the OrderComplete state.
Implementing the ShippingTask component
The Shipping Task component is simply a Web page that presents the order information and allows a shipper to indicate that the order was shipped. In this case, we will choose a human task implementation:
- In the OrderProcessing assembly editor, right-click on the ShippingTask component, and then select Generate Implementation... - Human Task.
- When the dialog box opens and asks where to put the implementation, click OK to accept the default. Also, accept the default name for the Human Task Component Handler dialog that opens.
You are now done with the ShippingTask component implementation! The default settings are sufficient for this example, and since you will not be enabling server security, the default authorization settings are fine.
This means that anybody who opens the Business Process Choreography explorer on the server can view and respond to pending shipping tasks. The Business Process Choreographer explorer and human tasks will be covered in detail in a future article in this series.
Implementing the CustomerCheck component and CustomerInformation import
You implement the CustomerCheck component using a set of business rules, which in this example, consists of two rules. The rule is simply that a customer whose identifier begins with "gold" is automatically considered a good customer; otherwise it runs a customer check. Authoring of Business Rules, and how to easily change them after deployment, will be covered in a future article in this series.
To implement the CustomerCheck component, follow these steps:
- In the OrderProcessing assembly editor, right-click on the
CustomerCheck component and click Generate
Implementation... - Rule Group. When the dialog box opens and
asks where to put the implementation, click OK to accept the
default. A new rule group displays, as in Figure 17.
Figure 17. CustomerCheck rule group
- Select checkCustomer, and then select Enter Destination
next to the Default Destination and select New Ruleset. For the
checkCustomerand click Finish. A RuleSet editor will open.
- Right-click Rules and select Add If-Then Rule twice to add two rules.
- In Rule1, in the If cell, click Condition, and then type
customerID.startsWith("gold") == false. You can also select each part of the expression from the lists that display as you type.
- In the Then row of the table, click Action and select Invoke.
- In the cells that appear within the Then row, select CustomerCheckPartner for Partner, checkCustomer for Operation, customerID for the customerID input, and customerOK for the customerOK output. This means that the input received by way of the customerID parameter is passed as the customerID parameter of the checkCustomer operation of the CustomerInformation import. Likewise for the customerOK output parameter.
- In Rule2, in the If cell, enter
customerID.startsWith("gold") == trueand in the Then cell, enter
customerOK = true.
The completed ruleset is shown in Figure 18.
Figure 18. The checkCustomer operation ruleset
For the CustomerInformation import, you will just leave it as an unbound import; that is, it is not set up to call any implementation. In the next article in this series, you will bind imports in one module to exports in other modules.
You have now completed the module, so in the next section you will deploy and test it.
Testing the OrderProcessing module
Now you can test the OrderProcessing application to see how it works by following the last set of steps. All of the necessary deployment code has already been generated behind the scenes as you were saving the contents of the various editors.
- Verify that there are no errors by switching to the Problems view. If you see any errors and do not know how to fix them, you can cheat and load the OrderProcessingPrebuilt module (you can download the Project Interchange file from the downloads section at the end of this article) and either test using that module, or compare it to the module that you built.
- Right-click the OrderProcessing module and select Test Module.
- In the test client that opens, select ProcessOrder for the
component and placeOrder for the operation, because that is the
kick-off operation for the order processing. Recall that the calls to
the ProcessOrder state machine are correlated on the orderNumber, so
the value that you enter is important: the same value must be used
when the other ProcessOrder operations are called. The other values
are not used in this example, so you can enter any values. For the
initial request parameters, enter
5for the orderNumber,
abcfor the productID,
1for the quantity and
123for the customerID, as shown in Figure 19.
Figure 19. Testing the OrderProcess module
- Click Continue, and after ensuring that a WebSphere Process Server is selected in the deployment dialog box, click Finish. You will need to wait while the server starts (if it isn't started already) and while the application deploys to the server.
After a few minutes, you will see events in the Events pane of the test client as service calls are made between components, as shown in Figure 21.
The first event displays at the initial call to the placeOrder operation,
which causes the ProcessOrder state machine to transition to the
CustomerBeingChecked state. During the transition, the line
Order has been placed. Setting Variables.
prints in the console.
The next event shows the call from ProcessOrder to the CustomerCheck component. Because the customerID was not prefixed with "gold", the business rule triggers a call to the CustomerInformation import, which ends up being emulated because it is an unbound import. At this point, a manual emulate event displays, as shown in Figure 21. The next set of steps complete the emulation and then the human task, once it has invoked the ShippingProcess component.
- To complete the emulation for the checkCustomer operation, enter
truefor the value of the customerOK output variable, then click Continue.
- When the ShippingProcess component calls the ShippingTask component, a human task is waiting to be completed. Open the Business Process Choreographer Explorer by switching to the Servers view, right-clicking the WebSphere Process Server instance, and selecting Launch - Business Process Choreographer Explorer.
- When the Business Process Choreographer Explorer opens, the My Tasks page will be open by default. Select the check box next to ShippingTask and select Work On. The order information displays as in Figure 20.
- Recall that the shipOrder operation of the ShippingTask interface
returns an Order business object. Ensure that you enter the same value
for the orderNumber, in this case
5, so that the correct instance of the ProcessOrder state machine receives the orderShipped message. Any values for the other order properties are sufficient because they are not used in this example.
- To complete the task, click Complete.
Figure 20. Completing the ShippingTask in the Business Process Choreographer Explorer
The ShippingTask activity is now complete and the NotifyShipped activity executes. In the console, you will see the rest of your print statements. More events appear in the test client as it calls the rest of the services calls. Figure 21 shows the log and the completed test.
Figure 21. Testing the OrderProcessing application
In this article, you explored some of the basics of building an application using WebSphere Integration Developer. You built components based on interfaces that you created, provided simple implementations for them, and then tested the application. In future articles, you will learn how to use other WebSphere Integration Developer tools to build a more substantial application.
More articles in this series
- Part 1: Get a driver's view of the WebSphere Integration Developer landscape
- Part 2: SOA development with WebSphere Integration Developer
|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
- 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