![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() | ![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Process Manager User's Guide
CHAPTER 5
This chapter discusses concepts and scenarios that go beyond the simple "straight-through processing" use cases that have been discussed so far. In particular, we will examine the Web Service Receive activity and the Synchronize Subprocesses activity. The Web Service Receive activity is useful in implementing design patterns that rely on incoming notifications or requests as part of an ongoing process. The Synchronize Subprocesses activity, on the other hand, is useful for collecting and resynchronizing the results from a previous fan-out (or parallel division of workflow to multiple subprocess instances) by an upstream activity.
To get the most out of this chapter, you should be familiar with WSDL-based Web Services, Composer action models, and concepts involving message mapping, fault messages, and link logic.
The Web Service Receive activity type allows you to implement the WSDL Request-Response and One-Way port type patterns. These are patterns in which the "endpoint" activity (representing the Web Service that will fire) does nothing until triggered by an incoming request. The target activity's implementation is, in this sense, passive—unlike the Notification and Solicit-Response scenarios, in which the underlying service is the requestor instead of the requestee.
The Web Service Receive activity must fulfill all the normal obligations of an activity in a process model. That means it has to be able to function as a link target, with timeout and retry behavior, fault behaviors, etc.
In this example, Activity 1 (a Subprocess activity) "fires" Activity2 (a Web Service Receive activity) via link L1. When and if Activity2 exits with a condition of true, its outgoing link (to Activity3) will be followed, but not until then. If Activity2 does not come back with an exit condition of true within the Timeout period (in this case, 7200 seconds: two hours), Activity2 will generate a _TimeoutFault
.
A key concept to understand is that the runtime engine doesn't run the service under Activity2. It merely provides appropriate input messages (as with any activity) at the proper time and collects the output message at the appropriate time. Incoming requests to the server cause the Web Service Receive's implementation to be invoked or run through appropriate triggering mechanisms (involving servlets, JMS listeners, or whatever), independently of the process engine itself. In other words, the web-service app that underlies the WSR activity is just a web service on a server, like any other web service, and its URL might be hit at any time, but the process engine only cares about (and will only respond to) that web service within the context of a given process, with all its timeout constraints, etc. Should a business partner hit the URL when the WSR activity is not active, the partner will likely just get a SOAP fault message back.
A typical WSR usage might be one in which a process is designed to send requests to various vendors, collect the first valid response, and continue on to do some kind of processing. Using the pattern shown in the above diagram, the roundtrip scenario could look like this:
The implementation for Activity1 might be an app that issues a request for quote (RFQ) via notifications to one or more external business partners who have web services designed to handle such requests.
Activity2 might be configured in such a way that the notified business partners have two hours to reply with a quote. If no reply is received (from any partner) within two hours, the activity generates a Timeout Fault.
Activity2's underlying implementation might be a web service that wakes up the process engine immediately upon receiving a valid quote.
Activity2 exits immediately if a reply is handled (transferring control to the next activity); or else exits with a Timeout Fault after two hours. (We're disregarding the System Fault case for purposes of this example.)
Activity3 might notify a person or department (or another app, etc.) that a bid was received from so-and-so.
Note that this is not a fan-out/fan-in scenario, but a "first responder wins" type of scenario. If you were going to notify multiple partners and collect multiple responses, you would want to use the Synchronize Subprocesses Activity (described further below).
It is possible to have multiple web services act as "the implementation" of a single Web Service Receive activity. This is because a Web Service Receive activity is built on top of a web service that waits to receive something—waits to be "hit."
In the example shown above, a Web Service Receive activity (situated between two activities, A1 and A2) is able to respond to any of three different web services that have been deployed as implementations for the activity. When the WSR activity "fires," the process simply waits for one of the three web services represented by URLs reply.target1, reply.target2,
and reply.target3
to receive input from a business partner. Each of the web services is a Composer application that contains a Find Waiting Activity action (as discussed in more detail in the next chapter). When one of the web services executes its Find Waiting Activity action—followed by a Release Waiting Activity action—the process continues of to the next activity, A3, assuming no fault conditions.
NOTE: If any business partner "hits" one of the three web services during a time when the WSR activity is not active (e.g., hasn't been fired; or has fired and timed out), the partner will receive an error message of some kind. In most cases, this will be a SOAP fault.
The Process Manager imposes no restrictions on what the implementation for a Web Service Receive activity should look like. This is true for Web Services in general. The authors of WSDL put no limitations on how a Web Service should be implemented, and there are also no restrictions on the transport mechanism used. A Web Service needn't use HTTP, for example, and payloads needn't be passed via SOAP.
The Process Manager, likewise, allows your Web Service Receive activity's implementation to take various forms: Composer web service, JMS service, or External (arbitrary implementation, not built in Composer). These choices are provided in a pulldown menu control on the Activity tab of the Object Properties dialog (see below).
Of course, for a Web Service to be a true Web Service, it should have a WSDL definition associated with it. Composer consults the WSDL when determining how to manage message maps for the Web Service Receive activity. In addition, since this is a Web Service Receive activity, the underlying service should implement either the WSDL One-Way or Request-Response port-type scenario. (The distinguishing characteristic of these two patterns is that the service implementing them is never the initiator of a transaction. The service is a receiver; you can think of the service as "listening" on a port.)
To use a Web Service Receive activity:
Design and implement the Web Service that will serve as the activity implementation. It should have its own WSDL Resource. (For information on how to create services and WSDL Resources in Composer, consult the eXtend Composer User's Guide).
If you created the Web Service inside another project, import the Web Service and its resources into the current project, which will contain your Process.
Create or open the Process in which you want to use the Web Service Receive activity.
Using the Web Service Receive variant of the Activity Tool (on the Process Designer toolbar), place a Web Service Receive activity icon on the process graph.
Draw links to and from the Web Service Receive activity the same way you would for any other kind of activity.
Bring the Object Properties pane into view (using View > Object Properties, if necessary).
Next to Component Type in the properties list, use the pulldown menu to select one of External, JMS Service, or Web Service, as appropriate. See illustration.
Next to Web Service Name, use the pulldown menu to select the Web Service that you built in Step 1. (This list is prepopulated with the names of all Web Services in the current project.)
Set any other properties that you want to specify on the Activity tab.
Add any data mappings that you want to add, using the Plus-sign icon.
In order for a process to make use of the Web Service Receive activity, there must obviously be an underlying implementation consisting of a web service that communicates via the One-Way or Request-Response pattern(s) described in WSDL. This service must, in turn, be capable of communicating its "finished" status (and in most cases, some kind of XML data) back up to the process engine. Such communication requires the use of Find Waiting Activity and Release Waiting Activity actions in a service's action model, as described in the next chapter.
NOTE: If you intend to use the Web Service Receive activity type, be sure to read about Find Waiting Activity and Release Waiting Activity actions in the next chapter.
The Synchronize Subprocesses activity is similar to the Web Service Receive activity in that it, too, assumes an implementation that waits passively for incoming data and that may be invoked numerous times before it finally exits. Unlike the Web Service Receive activity, a Synchronize Subprocesses activity must use a Composer Component (an XML Map Component, for example) as its implementation.
The purpose of the Synchronize Subprocesses activity is to allow data from numerous input activities to be collected into a single activity, in situations where the number of inputs is not known until runtime. In other words, this represents a scenario that (due to an indeterminate number of links) can't be drawn on a process graph. It is sometimes called a "fan-out/fan-in" scenario.
The fan-out activity in this diagram might represent a start activity in a process that receives a batch of work items. The number of work items, however, is not known until runtime. Suppose a subprocess called DoWork can process exactly one work item, then pass it on to the next activity. Ideally, you'd want the start activity to be able to fan out N work items to N instances of DoWork, have those instances execute in parallel, then collect all the results of the various DoWork instances at a central Fan-In Activity, as shown.
The problem is that this pattern can only be drawn if the maximum number of possible instances of DoWork (the maximum batch size) is known in advance. If it were possible to know, for instance, that a batch can never hold more than 12 work items, then you could place 12 activity icons on the graph, representing 12 launchable instances of DoWork, and connect links from the Fan-Out activity to each instance of DoWork (as well as outgoing links from each DoWork to a Fan-In Activity.) A simple XPath condition on each link could determine (by looking at the output from the Fan-Out activity) whether a given link should fire based on whether the appropriate source XPath contains data.
An explicit graph of the type just described will work. It wouldn't be pretty to look at, and the data mappings would be tedious to spell out, but it would work. The problem is that six months from now, someone could decide that the maximum batch size needs to be 200 instead of 12. Or, there may be no limit to the batch size. What then?
The Synchronize Subprocesses activity is designed to handle resynchronization of the results of a fan-out. The process engine performs certain services on behalf of the Synchronize Subprocesses activity, and the activity's implementation must be designed with certain runtime behaviors in mind. The salient points to bear in mind are:
The Fan-Out Activity (which can be any of the standard Process Manager activity types) invokes N instances of a Subprocess activity. The instances are spawned from Process Execute actions inside the Fan-Out's action model, as part of a loop.
Because the "work activities" are subprocesses and are spawned (rather than called synchronously), each subprocess returns a ProcessID to the Fan-Out activity immediately.
The Fan-Out activity implementation should collect the ProcessIDs under a known XPath in Output
. That XPath must, in turn, be specified in the property sheet for the Synchronize Subprocesses activity as shown here:
The component that provides the underlying implementation of the Synchronize Subprocesses activity need not know about the list of ProcessIDs. The runtime engine will call the implementing component the appropriate number of times, based on this list; then it will pass control (when every subprocess has finished) to the next link or links in the chain, barring a fault condition. Thus, the implementing component does not need to know that it is being used as part of a loop.
Each time the fan-in implementation is fired, the Input
message part will contain the output from a subprocess that just finished. It is up to the Synchronize Subprocesses implementation (the fan-in component) to process the newly acquired data as needed. Usually, this will mean accumulating it onto Output
, for reasons explained below.
When all subprocesses have returned, the activity returns (barring a fault condition) and the parent process continues down the normal control chain.
The Synchronize Subprocesses activity will always have at least three message parts: Input
, Input1
, and Output
. The activity implementation will have DOMs corresponding to these part names as well, but the parts have unique roles and an implementation should be designed with those roles clearly in mind.
From the implementation's point of view, the Input message part is where subprocess output will be received. Each time a spawned subprocess returns, its output gets passed to the merge component's Input
. (The "merge component" here means the Synchronize Subprocesses activity implementation: an XML Map component, JDBC component, or whatever.)
In the case of most other activity types, data from the previous activity's Output
is passed into the target implementation's Input
DOM. In the Synchronize Subprocesses case, however, this is not true, because the activity that fires the Synchronize Subprocesses activity is not really the data source of interest. See below.
The Synchronize Subprocesses activity implementation (or merge component) is interested in data provided by the subprocess instances that were spawned. It looks to Input
to find that data. Each time the merge component is fired, it sees a single work-item's worth of data in Input
.
The Synchronize Subprocesses activity implementation will typically map the Input1
DOM straight to the Output
DOM before doing anything else. That is to say, there will usually be an XML Map action at the top of the implementation's action model that looks like:
This is because the merge component's Output
part will be fed back into Input1
on every subsequent invocation of the component. See discussion below.
In order to allow the Synchronize Subprocesses activity implementation to accumulate or consolidate "work items" into a single document, by adding subprocess returns one at a time to an incrementally built DOM, the Synchronize Subprocesses activity recycles its implementation's Output
back to Input1
. In other words, on invocation N, the implementation receives, in Input1
, the Output
from invocation N–1. (On invocation zero, Input1
is empty.)
See diagram below.
You can choose to have the Synchronize Subprocesses activity raise a Fault message according to one of two policies: Fail on Any Fault, or Fail if All Fail. In the first instance, the activity faults out as soon as any one of the feeder activities (the data-producing subprocesses) gives a fault. In the second case, all of the spawned subprocesses must return before a fault is generated. In either case, if the Synchronize Subprocesses activity results in a fault, the process of which it is a part will terminate unless the fault is handled (just as it normally would). Therefore, as a safeguard against a single fanned-out subprocess instance failing your whole process, you should take time to "think through" a robust fault-handling scheme.
Any time an activity (such as a subprocess or Web Service Receive activity) is in a wait state, waiting to receive a response to some request that was made asynchronously by another activity, it is said to be a waiting activity. In the wait state, the activity is not "running" in the normal sense of the word; it is not in memory. The activity implementation might be a Web Service that operates according to the Request-Response or One-Way port types of WSDL. It gets fired when a request comes in via HTTP to the server, or via a message sent to a JMS message listener, etc. After the service is finished, the activity for which it is the implementation (the waiting activity) needs to "wake up" and notify the process engine so that the proper process instance can continue to execute the appropriate flow pattern.
But an activity implementation, being merely an application or service of some sort, doesn't necessarily know (nor should it know) that it is being used in a stateful process. The application (the activity implementation) might be a generic, reusable, multi-role application or component that gets invoked by external clients as well as by local applications. It may be a part of several different process models. At any one time, there might be dozens of process instances using the component as an activity implementation. When an instance of the component fires, it has no idea who called it or why; it doesn't magically know if it is being used as an activity implementation in a running process. See below.
If an activity is waiting for its underlying implementation to produce output, the underlying service or component has to have some way of hooking back into the correct process instance, because numerous process instances (possibly belonging to different process models) might be using the same implementation. A correlation value of some kind must be passed into the waiting activity's implementation so that the implementation can get the activity out of the wait state and let the proper process instance resume navigation.
NOTE: The particulars of how and when to specify a correlation value will be discussed in the next chapter.
The scenario, then, is this:
The activity that makes the original outbound notification to an external serviceor business partner must pass a correlation value to the service. This can be a custom CorrelationID in conjunction with the Process name, or it can be a ProcessID in conjunction with the Activity name. (See the next chapter for details.)
The web service that serves as the implementation for the Web Service Receive Activity must get the correlation value back from the external service (business partner).
The web service (WSR implementation) must be a Composer service with an action model that contains a Find Waiting Activity action. (New Action > Process > Find Waiting Activity.) The correlation value(s) will be used in this action as a means of looking up the appropriate waiting activity in the appropriate process.
Once the Find Waiting Activity action has successfully executed, it must be followed by a Release Waiting Activity action. (New Action > Process > Release Waiting Activity.)
When the Process Manager has been installed as part of a Composer installation, all component editors for all component types (JDBC, XML Map, JMS, Telnet, etc.) have six Process-related actions available for use in any action model:
These actions are available off the Process submenu in the New Action menu. You can use them in the action model for any type of Composer component or service (XML Map component, JDBC component, etc.), but if they're used in a component, the component should be wrappered in a Composer web service.
Five of the six activities are related to Waiting Activity functionality. All such functionality assumes the presence of an activity whose implementation follows a One-Way or Request-Response type of communication pattern. These are patterns in which the web service waits, passively, for an external request.
Find Waiting Activity and Release Waiting Activity actions will be used together in most scenarios that involve waiting activities, regardless of the nature of the associated business tasks. That's because both are needed in order to "wake up" a Web Service Receive activity once it has been enabled.
When process flow reaches a WSR activity at runtime, the process goes to sleep and only wakes up again when:
In other words, the coupling between a WSR activity and its underlying implementation is quite loose. A Web Service Release activity can be thought of as simply a place in the process flow where the process goes to sleep until it is woken up either by an alarm clock (i.e., the activity times out) or by a web service that knows how to wake the process up again.
For an in-depth discussion of Waiting Activity actions and their usage, see the next chapter.
The actions called Browse Waiting Activities, Lock/Unlock Waiting Activity, and Reassign Addressee add optional functionality designed to make it possible to use waiting activities in a human-intervention type of workflow, where human operators perform tasks in response to notification by activities. It is common in this type of flow for notifications to be sent to human operators, who will ultimately post work back to the process via waiting activities. This type of scenario is discussed in greater depth in the following chapter.
The concept of an Addressee is exposed in some of the "waiting activity" action dialogs. This allows work items (that is, message parts, or node branches within parts) to be assigned to specific individuals according to their roles, as part of a running process. The individuals in question can be notified of arriving work via an activity designed for that purpose; and the process instance can call on a Web Service Receive activity (or other "waiting activity") to receive various individuals' work back into the system.
The notion of work-item Priority is also exposed in this system.
NOTE: Addressee and Priority are initially specified in the Object Properties panel of the Web Service Receive activity. (The Addressee and Priority properties will not be visible in other activity types. A Web Service Receive activity must be selected in order to see these properties.)
Work items can be marked as locked for exclusive use by one individual, programmatically, through the Lock/Unlock Waiting Activity action.
Work items can be reassigned to different individuals via the Reassign Addressee action.
In addition, waiting activities representing the work queues of specific individuals can be browsed or tallied using the Browse Waiting Activity action.
Through the creative use of these actions, you can develop sophisticated (yet robust and easy to test) workflow systems involving work queues, work items with varying priorities, human operators with roles, and so on.
Copyright © 2003 Novell, Inc. All rights reserved. Copyright © 1997, 1998, 1999, 2000, 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved. more ...