The full potential of the Web services framework will not be realized until complex interactions are properly supported. Although no single standard has yet emerged, Web services flow (or process) languages, such as the Web Services Flow Language (WSFL) and XLANG), provide the means to deal with them. This chapter, from Java Web Services Unleashed, reviews the basic concepts underlying these languages, drawing mainly from WSFL.
This is Chapter 18: Web Services and Flows (WSFL) from the book Java Web Services Unleashed (ISBN:0-672-32363-X) written by Robert Brunner, Frank Cohen, Francisco Curbera, Darren Govoni, Steve Haines, Matthias Kloppmann, Ben Marchal, Scott Morrison, Arthur Ryman, Joe Weber, and Mark Wutka, published by Sams Publishing.
© Copyright Pearson Education. All rights reserved.
Chapter 18: Web Services and Flows (WSFL)
Chapter 18: Web Services and
Flows (WSFL)
By Francisco Curbera and Matthias Kloppmann
In This Chapter
- Service Flow and Service Composition
- Flow Modeling Concepts
- Flows as Compositions of Web Services
- Exposing Flows as Web Services
- Public and Private Flows
- Global Models
- References
The overall aim of Web services is to provide a standards-based
framework to enable application-to-application interaction. Simple interactions,
in particular stateless ones, can be modeled as single operation invocations or
message exchanges with a service; WSDL and SOAP provide convenient support for
this type of basic interaction. Richer interactions typically involve multiple
invocations flowing between two or more services in a peer-to-peer
settingthat is, a scenario in which all participants potentially act as
both clients and servers. This is the model of interaction prevalent even in
simple business transactions, both in the business-to-consumer and (especially)
in the business-to-business scenarios. Even a process as simple as ordering
merchandise online involves at least three partiesa customer, an
e-commerce retailer, and a shipperas well as direct interactions between
the three of them.
The full potential of the Web services framework will not be realized until
complex interactions of this kind are properly supported. Although no single
standard has yet emerged, Web services flow (or process) languages, such as the
Web Services Flow Language (WSFL) and XLANG), provide the means to deal with
them. This chapter reviews the basic concepts underlying these languages,
drawing mainly from WSFL.
Service Flow and Service Composition
Complete representations of complex service interactions rely on two basic
concepts: service flow and service composition. The service flow is a description
of how the service operates. In business environments, the service flow is a
representation of the business process that it implements. By revealing the
internal operation of the service, the flow lets users and possible business
partners know how the service should be used. In particular, the flow describes
the order in which the operations the service provides should be used, and the
logic the service follows to process requests. Following a long-standing tradition
in the field of business process modeling, WSFL uses a flow model to represent
service flows. The flow model itself is presented in the section Flow
Modeling Concepts.
A flow's individual steps can be realized through a multitude of possible
implementations, from manual realizations performed by people to automatic implementations
performed by software. The usage of Web services as particular realizations
of the individual steps of a flow is described in the section Flows
as Compositions of Web Services.
Flows themselves are of course services, too, though more complex ones. It
must therefore be possible to make them available as Web services. The section
Exposing Flows as Web Services; shows how
this can be done.
Flows can provide different levels of description of the business process followed
by a Web service. The complete description allows a flow language interpreter
(a flow engine) to actually implement all the service functionality with
no other input than the service flow specification itself. Typically, this level
of description is not published, because it may reveal details of the hosting
enterprise's operation or its trade secrets. The complete flow is in this
case referred to as the private flow of the service. A simplified flow
is published instead, containing just the information partners need to interact
with the service. This public flow differs from the private one only
in the level of detail provided, not in the underlying representation model.
The section Public and Private Flows; deals
with public flows.
Service composition is the second fundamental concept that is required to represent
complex service interactions. Composition refers to the act of putting
together two or more existing services to provide new functionality not present
in the original ones, either in the form of a new service or in the form of
a distributed service interaction. A flow typically accesses other Web services
in the course of its operation, thus becoming a composition of services itself:
It defines a usage pattern for existing services and optionally offers the composed
functionality as a new service. A second type of composition occurs when multiple
services interact following a certain interaction pattern to achieve some business
goal. The nature of this composition is intrinsically distributed: Unlike the
flow-based composition, these compositions are not orchestrated from a single
point of control or flow engine. Service composition in WSFL is described in
some detail in Flows as Compositions of Web Services;
and Global Models.
The rest of this chapter develops the themes outlined here in some detail,
using the flow depicted in Figure 18.1 to
introduce the basic concepts of service process and service composition. You
will notice a significant difference between this and other chapters in the
book: There is no Java code provided here. The reason, obviously, is that there
is no support available yet for any of the proposed Web services flow languages.
The goal of this chapter is thus limited to introducing the fundamental concepts
of service flows and compositions.

Figure 18.1
Cell phone ordering service sample flow.
Flow Modeling Concepts
In WSFL, flow models are used for the specification of complex interactions
of services. A flow model describes a usage pattern of a collection of available
services, so that the composition of those services provides the functionality
needed to achieve a certain business goalthat is, the composition
describes a business process. The flow model specifies precisely how those
services (steps in the flow) are combined, specifying in which order they have
to be performed (including the possibility of concurrent execution), the
conditional logic deciding whether an individual step or a group of steps have
to be performed at all or should be looped, and the passing of data between the
involved steps.
Figure 18.1 shows an example of a flow model
describing a simplified ordering process for a cell phone that continues and
evolves throughout this chapter. It consists of a set of business tasks that
are executed in a certain order, although some tasks may be skipped. The example
flow starts with the receipt of an order for a new cell phone. If the requestor
is not known as a customer, the credit history is checked first, and then a
customer account is created. Neither of these tasks need to be done for an existing
customer. Depending on retrieved knowledge about the requestor, the order might
be rejected. Otherwise, the order is processed. The credit card is charged,
a bill is sent, a new phone number is assigned, the phone is sent, and so is
a note informing of its delivery.
Data produced by a certain task in the flow may be used by a subsequent task;
for example, the customer account data is used to send the bill.
From the example, you can already see that the key ingredients for the
description of a flow model are the individual business tasks that have to be
executed, the specification of the control flow describing the order of their
execution and the conditional logic, and the specification of the associated
data flow describing the passing of data between them. In WSFL, those three
concepts are described by activities, control links, and data links.
Activities
An activity is a single step in a flow. It represents a business task
that potentially has to be performed as part of the business process the flow
model describes. Whether it is actually performed during the execution of a
specific flow depends on the conditional logic of the control flow into which it
is embedded.
WSFL distinguishes between an activity and its implementation. The
implementation describes an actual operation that is invoked when the
activity is reached during execution of the flow. The activity, on the other
hand, describes how this operation is embedded into the flow. An
operation in this context can be anything needed to realize the
particular business task. The most obvious realization is the invocation of a
piece of code. Another very common realization in existing workflow products is
the involvement of human beings performing a task manually.
In the example, the CheckCreditHistory activity is described by the following
WSFL fragment:
<activity name="CheckCreditHistory">
<input name="CustomerData" message="tns:Customer"/>
<output name="Result" message="tns:CreditWorthiness"/>
<implement>
<internal>
<!-- Implementation is provided by check method of
an EJB -- outside WSFL scope -->
<ns1:ejbMethod xmlns:ns1="..."
ejbNameJndiName="/finance/creditHistory"
operation="check" />
</internal>
</implement>
<!-- Other properties describing embedding into
(control and data) flow -->
</activity>
The fragment specifies that the CheckCreditHistory task expects a
message of type Customer and produces a message of type
CreditWorthiness. Both messages are WSDL messages as described Chapter
11.
Note
The tns (this name space)
prefix is needed because messages are actually XML-qualified names that are
qualified by associated name spaces.
For the example, we assume that the activity is implemented by a certain
EJB's check method. Note that the specification of the actual
implementation is from a different name space, because WSFL addresses this as an
extensibility element outside the WSFL scope.
Additional properties of the activity relate to its embedding into the
control and data flow, which is covered in the following section.
Control Flow
The control flow of a flow model specifies the execution order of the
individual business tasks to be performed, and the conditional logic specifying
whether they should be performed at all, or possibly looped. The need for
executing two business tasks in a certain order follows from logical
dependencies between them; if no such dependency exists, they can be performed
concurrently, thus speeding up the execution of the flow.
In WSFL, a control link is a relationship between two activities,
A1 and A2,that prescribes an execution order:
A1 has to be completed before A2 can be started. In WSFL,
the set of all activities and the set of all control links together describe a
directed, acyclic graph.
Figure 18.2 has more control flow detail
for the first part of the example flow model. Here, the control link between
the
ReceiveOrder activity and
CheckCreditHistory activity
indicates that the latter cannot be started until the former has completed.
Whether it is actually started depends on the control link's optional transition
condition attribute, which is evaluated at the flow's run-time. Depending
on that evaluation, control is either passed along the control link, or the
control link marks the start of a dead path, which is eliminated from the flow
during its run-time.
WSFL doesn't distinguish between alternate branches where one is taken
depending on a certain condition (switch) and parallel branches that are all
taken concurrently (fork). In the WSFL model, multiple control links originating
from the same activity always denote a fork, possibly followed by a dead-path
elimination of some of the parallel branches.

Figure 18.2
Flow model: control links, transition conditions, and join conditions.
In the example, the following lines specify that this path is to be taken
only if the activity ReceiveOrder returned no customer ID, that is, when nothing
is known about the customer:
<controlLink source="ReceiveOrder" target="CheckCreditHistory"
transitionCondition="customer/id=null" />
The two control links leading to the ChargeCreditCard activity
specify a control join, stating that this activity can be started only after
both the ReceiveOrder and CreateCustomerAccount activities are
complete. Completion is achieved either by successful execution or by dead path
elimination. When an activity is the target of more than one control link, a
WSFL join element associated with the activity describes how the activity is
dealt with.
In the example, the following lines state that the ChargeCreditCard
activity is executed only after all its incoming control links have been
evaluated, synchronizing the parallel paths (deferred evaluation of the join
element, the only option currently offered by WSFL), and only if at least one of
those control links evaluated to true:
<activity name="ChargeCreditCard">
<input name="CreditCardData" message="tns:CreditCard"/>
<output name="Result" message="tns:CreditCardChargeRecord"/>
<implement>...</implement>
<join condition="link1 OR link2" when="deferred" />
</activity>
<controlLink name="link1"
source="ReceiveOrder" target="ChargeCreditCard"
transitionCondition="customer/id != null &&
customer/credit=ok " />
<controlLink name="link2"
source="CreateCustomerAccount" target="ChargeCreditCard" />
Data Flow
A flow model's data flow specifies how the output message of a given
business task is used by one or more (subsequent) business tasks. Put the other
way round, the data flow specifies how the input message of a given business
task is created from the results of one or more (preceding) business tasks or
the input message of the flow itself. In that the involved message types
typically don't match, the mapping from an output message to a subsequent
input can involve transformations such as the renaming of message parts.
In WSFL, a data link is a relationship between two activities, A1
andA2, that describes that A2 uses the result data of
A1.
Figure 18.3 shows the signatures of the
first few activities involved in the example flow model. The dashed arrows represent
data links.
The following lines specify that the field customerInfo from the
data part of the Order message, which was the result of the
ReceiveOrder activity, is mapped to the record part of the
Customer message that is the input to the ChargeCreditCard
activity:
<dataLink source="ReceiveOrder" target="ChargeCreditCard">
<map sourceMessage="tns:Order" targetMessage="tns:Customer"
sourcePart="data" sourceField="customerInfo"
targetPart="record"/>
</dataLink>

Figure 18.3
Flow model: inputs, outputs, and data links.
As the example shows, WSFL allows the data flow to be specified independent
from the control flow, as long as the execution order constraints still
guarantee that a message is produced before it is used by another activity.
Generally speaking, the data flow has to be parallel to the control flow.
It is possible that an activity receives data from multiple other activities
(a data join). In this situation, WSFL allows for the detailed
specification of the materialization of that activity's input message,
using either an override technique such as "last writer wins," or a
merge technique that can be specified via an XSL transformation with multiple
inputs. This kind of elaborate container materialization is not needed for the
current example, and so it is not detailed further here.
Flow
If you put the ingredients described in the previous sections together, you
have already completed the specification of a simple flow model involving
activities that are implemented by internal operations, like this:
<flowModel name="cellPhoneOrder">
...
<activity name="CheckCreditHistory">
<input name="CustomerData" message="tns:Customer"/>
<output name="Result" message="tns:CreditWorthiness"/>
<implement>
<internal>...</internal>
</implement>
</activity>
...
<controlLink source="ReceiveOrder" target="CheckCreditHistory"
transitionCondition="customer/id=null" />
...
<dataLink source="ReceiveOrder" target="CheckCreditHistory">
<map sourceMessage="Order" targetMessage="Customer"
sourcePart="data" sourceField="customerInfo"
targetPart="record"/>
</dataLink>
...
</flowModel>
Flows as Compositions of Web Services
The previous sections introduced the basic building blocks of a flow, without
focusing too much on the actual realizations of the flow's activities.
Although those realizations could be anything from manual realizations by human
beings to an assembler program, the goal of WSFL is obviously not so much the
composition of flows that coordinate internal implementations, but rather the
composition of flows that perform the coordination of Web services, where the
Web services implement individual activities.
For that, WSFL first introduces the notion of a service provider as an
abstraction for a business partner that offers one or more WSDL services that
are used within the flow model. Second, a WSFL activity can then refer to a
specific operation that a specific service provider provides, as an alternative
to the internal implementation you already saw in the previous sections.
Service Providers and Service Provider Types
Service providers are abstractions for the concrete business partners with
which a flow model interacts. Service providers are declared in a WSFL flow in
the same way that variables are declared in a Java program. A type
("service provider type") is assigned to each service provider. The
type is essentially nothing but a predefined list of WSDL portTypes, and it
gives a formal representation of the service or services that each service
provider must offer to participate in the flow. The actual binding between a
service provider variable of a given type and a concrete business partner is a
separate step, which is described by the locator element.
The distinction between a service provider and a service is an important one:
Flow models specify the usage of a service instance of a given type, rather
than the service itself. Several flows can use a single Web service simultaneously,
whereas a single flow model can use more than one provider of a given service
type. (Whether or not the service type is supported or bound to the same service
is in principle irrelevant; see the section Locators,
however). Coming back to the example, Figure
18.4 shows an updated version of the flow model, where three steps have
been outsourced to business partners.

Figure 18.4
Flow model using Web services.
WSFL requires that the business partners with which the flow model
interoperates are declared as service providers (of the appropriate type). In
the example, there are two, which are made available at the flow model level as
follows:
<flowModel name="cellPhoneOrder">
<serviceProvider name="Partner1" type="CreditServicesProvider"/>
<serviceProvider name="Partner2" type="LogisticsProvider"/>
...
</flowModel>
This simply declares two global variables at the flow level to be service
providers of the specified service provider type. A service provider type in
WSFL describes the external interface a business partner makes available, which
can consist of multiple port types and multiple operations.
The specification of service provider types is also part of the WSFL
definitions, in an element preceding the flow model.
In the example, the following lines indicate that the
CreditServicesProvider offers two operations from two port types (and a
similar definition for the LogisticsProvider, which is not shown
here):
<serviceProviderType name="CreditServicesProvider"
<portType name="creditHistoryHandler">
<operation name="check"/>
</portType>
<portType name="creditCardHandler">
<operation name="charge"/>
</portType>
</serviceProviderType>
Locators
The declaration of the service providers with which a flow interacts is
separated from binding those service providers to actual business partners that
offer the required services (according to the associated service provider type).
Although it is possible and often desirable to always use the same business
partner as a certain service provider, sometimes more dynamic binding mechanisms
are needed. A foremost example is UDDI lookup: Service providers of a given type
are looked up in a UDDI directory according to some criteria, then the most
suitable service among the retrieved set (according to some quality of service
criterion) is selected and bound.
In WSFL, the locator element covers the entire range of possible bindings,
locating the actual business partner that acts as a specific service
providereither statically or dynamically.
The example has so far declared two global variables at the flow level that
represent business partners with which the flow is interacting, and has defined
the required interface the partners have to provide, described by their service
provider type. It has not yet specified the concrete partners, that is, how
these variables are bound. A WSFL locator element specified this as part of the
service provider declaration.
The simplest kind of locator in WSFL is a static locator, which directly
refers to a WSDL service that provides the required operations. Observe that the
service is then identified by its namespace-qualified name, as defined in the
corresponding WSDL file. It appears in the example as follows:
<flowModel name="cellPhoneOrder">
<serviceProvider name="Partner1" type="CreditServicesProvider">
<locator type="static" service="abc:qualityCreditServices"/>
</serviceProvider>
...
</flowModel>
A second possibility is a dynamic locator that uses UDDI (see Chapter 9) to
dynamically find a suitable service provider of the required type:
<flowModel name="cellPhoneOrder">
...
<serviceProvider name="Partner2" type="LogisticsProvider">
<locator type="uddi" bindTime="firstHit"
selectionPolicy="user-defined" invoke="leastcost.wsdl">
<uddi-api:find_service businessKey="uuid_key" generic="1.0"
xmlns:uddi-api="urn:uddi-org:api">
...
</uddi-api:find_service>
</locator>
</serviceProvider>
...
</flowModel>
In this example, the flow engine uses UDDI to locate Partner2, the
logistics provider, when an operation this partner provides is needed for the
first time (firstHit). The flow engine executes the specified UDDI
query, which returns a list of possible providers, which the flow engine then
filters using a user-defined routine to return the cheapest provider. This
locator type provides for many more options not detailed here.
There are other locator types. Internal activity implementations (as described
in the Flow Modeling Concepts section) are
actually represented as operations a service provider implements with a locator
type of local (The earlier discussion omitted that detail.) Finally,
with a locator of type mobility it is possible to use a data field
from a message to locate a service provider.
Note
A more thorough description of locators and their options is in section 4.4.3
of Web Services Flow Language (WSFL) (see the References
section).
Outsourcing Activity Implementations: Export
After the service providers the flow model uses are declared, and given the
definition of their associated service provider types, the implementation of an
outsourced activity simply needs to reference an operation a service provider
offers, as shown in the following example:
<activity name="CheckCreditHistory">
...
<performedBy serviceProvider="Partner1"/>
<implement>
<internal>
<target portType="creditHistoryHandler" operation="check"/>
</internal>
</implement>
</activity>
Thus, the Check operation that is part of partner 1's
CreditHistoryOperations port type implements the flow model's
CheckCreditHistory operation. This is well defined, because partner 1
has been declared to be of type CreditServicesProvider, and thus is
guaranteed to provide that operation.
Note
The model WSFL uses for outsourcing an implementation is in fact more complicated
than presented here. The concept, however, is essentially the one that is
presented here. It would not make sense in this short overview to go over
the details of WSFL activity implementations. See Section 4.6 in the Web
Services Flow Language (WSFL) (see the References
section).
Exposing Flows as Web Services
Having built a flow model implementing the cell phone ordering process, the
next step is to make it available so others can use it. To do this, the flow
model itself is defined as a service provider implementing a particular service
provider type.
You can denote the flow's individual activities that implement this
service's operations by "exporting" them, that is, by making them
available for direct interactions with service clients. Still left open is how a
flow's concrete instance actually comes to life and vanishes again after it
is completedthis is addressed by the flow model's life cycle
operations.
After you have these ingredients together, it is possible to use WSDL
services and other WSFL flows to recursively compose flows.
Flow Model as Service Provider
Figure 18.5 highlights the interface to
which the flow model's client connects. The flow's interface contains
four operations, one inbound and three outbound, depicted as arrows that are
graphically connected to the activities they implement via dashed lines. Initially,
the client using that interface sends a request for a new cell phone, upon which
he receives either a rejection or a bill, which eventually is followed by a
delivery note (and the physical delivery of the phone, which is outside the
scope of a software solution).

Figure 18.5
Externalizing a flow as a Web service.
For this, you can define a port type and service provider type as
follows:
<portType name="cellPhoneOrderHandler">
<operation name="acquireCellPhone">
<input name="theOrder" message="tns:Order"/>
</operation>
<operation name="reject">
<output name="theRejection" message="tns:RejectionNotice" />
</operation>
...
</portType>
<serviceProviderType name="cellPhoneOrderProvider">
<portType name="cellPhoneOrderHandler"/>
</serviceProviderType>
Given these definitions, the flow model can be defined to be a service
provider of that service provider type by the actual flow model declaration:
<flowModel name="cellPhoneOrder"
serviceProviderType="cellPhoneOrderProvider">
...
Exported Activities
You have previously seen (in the section Outsourcing
Activity Implementations: Export) how you can outsource an activity's
implementation to an external service provider by using the internal
element to specify an activity's implementation. The use of the internal
element is necessary when the connection to the external provider is kept private
to the service, in the sense that it is not carried through a public WSDL interface;
that is, it is not mediated by an operation in the service provider type that
the flow declares.
Alternatively, an activity's implementation can be provided by exporting
it. Exporting an activity makes it visible to the flow's clients in the
form of an operation on the flow's service interface. In this case, an
export element replaces the internal element used before, and
a nested target element identifies the operation in the flow's own
interface that is mapped to this activity.
Detailing the Reject activity to make use of export produces the
following WSFL fragment:
<activity name="Reject">
<input name="orderData" message="tns:Order"/>
<implement>
<export>
<target portType="cellPhoneOrderHandler" operation="reject"/>
...
</export>
</implement>
...
</activity>
When an activity's implementation is exported, the flow engine executes
the activity by either receiving an invocation from a client (if the operation
to which the activity is exported is one-way or request-responsethat is,
an inbound operation), or by invoking an operation on a partner (when the operation
mapped to the activity is an outbound operationthat is, notification or
solicit-response). For example, the reject operation in the preceding example
is a notification operation on the phone ordering service interface, but corresponds
to the invocation of a one-way operation in the customer interface (which is
to say that the customer must be able to receive the rejection, and implies
a peer-to-peer interaction model, see Global Models).
Because of the uniform treatment that WSDL gives to inbound and outbound operations,
WSFL deals with both cases in the same way.
Note
In WSFL, a plug link can be provided inside the export element to
indicate the operation in the target provider that is actually being invoked.
You do not need to be concerned with this level of detail at this point. Plug
links are introduced in the section Plug Links;
additional details can be found in sections 4.5 and 4.6 of the WSFL specification
(see the References section).
Note that in the example the message types of the activity and the exported
operation don't match. In this case, an additional map element is
required to perform the message transformation. The full specification of the
export element from the preceding example would then be as follows:
<export>
<target portType="cellPhoneOrderHandler" operation="reject"/>
<map sourceMessage="tns:Order" targetMessage="tns:RejectionNotice"
sourcePart="data" sourceField="customerInfo"
targetPart="customerData"/>
</export>
Life Cycle Operations, Flow Input, and Output
Many instances of a given flow model can execute at the same time on the
associated run-time infrastructure. In WSFL, a new instance of a flow is created
with either the call or spawn operation.
Call is defined as a WSDL request-response operation where the input
message is the input of the flow, and the output message is the result from the
flow. Spawn is defined as a WSDL one-way operation where the input
message is the input of the flow. Both operations can be exported (that is,
exposed to clients) with a different name and signature.
Thus, the more precise definition of the sample flow model doesn't
represent the AcquireCellPhone operation as the flow's first
activity, but as an exported spawn operation, creating the flow
instance and passing input data. It also introduces a node representing said
flow input data (a flow source), replacing the previously present
ReceiveOrder activity:
<flowModel name="cellPhoneOrder">
serviceProviderType="cellPhoneOrderProvider">
<flowSource name="ReceiveOrder">
<output name="orderData" message="tns:Order"/>
</flowSource>
<export lifecycleAction="spawn">
<target portType="cellPhoneOrderHandler" operation="acquireCellPhone"/>
</export>
<activity name="CheckCreditHistory">
...
</activity>
...
<controlLink source="ReceiveOrder" target="CheckCreditHistory"
transitionCondition="customer/id=null" />
...
Additional life cycle operations are available:
A flow can be suspended through the use of the suspend
operation. When suspended, the flow's execution is discontinued, but the
flow still exists in its current state.
A suspended flow can be resumed through the use of the resume
operation. Execution of the flow continues from the state where it was
suspended.
-
The current state of a running flow can be queried through the use of the
inquire operation. This enables a business partner to find out
how far a given business process's execution (seen via its public flow
interface, as described in the Public and Private
Flows section) has already progressed.
A running flow can be terminated. This aborts the flow's execution
at its current state.
All the life cycle operations are offered as WSDL operations taking a flow
instance ID as a parameter. The operations can be exported via an
export element, as in the example in the Exported Activities
section.
Recursive Composition
You have seen that a flow utilizes operations provided by several other
services as the implementation of its activities. Another way to put this is to
say that a flow defines a composition of services by specifying a certain
usage pattern of its service providers' functionality. That is, the flow
combines the operations made available by its providers to achieve a given
compositional goal. You have also seen that a flow model itself can implement a
certain service provider typethat is, it can become a service itself,
offering a set of WSDL interfaces to possible clients. In particular, the flow
could become part of yet another service composition itself. The result is a
mechanism by which services can be recursively composed following a flow
composition model.
In general, this form of composition assumes a peer-to-peer interaction model
between services, in which the flow can invoke and be invoked by other services.
However, the compositional model provided by flows is a centralized model, in
which the composition is fully orchestrated from a single control point: the
executing flow engine. Fully distributed compositions of services are introduced
in the section Plug Links.
A special case of flow composition is based on hierarchical interactions
between services, as opposed to the more flexible peer-to-peer model. In this
case, an entire flow model can provide the implementation of a single activity
of another flowthat is, it becomes a sub-flow of the invoking flow. You
can achieve this kind of composition by using the flow model's
Call operation to implement the other flow's activity. Input data
from the activity is then passed to the flowSource of the sub-flow, and
data from the sub-flow's flowSink is passed back to become the
output of the activity.
Public and Private Flows
The introduction to this chapter mentioned the important fact that flow
languages are used both to provide users of the service with a description of
its behavior, and to actually implement the service. When used to describe
service behavior, the information provided is strictly limited to what partners
need to know to successfully interact with the service; implementations, on the
other hand, must contain all the details that would enable a compatible
interpreter to execute the service on behalf of requesters.
This section briefly reviews these two requirements and shows how a
service's public and private behavior are related in a typical case.
Defining Service Behavior
The behavioral description of a service is the first and most important task
of a flow language in the Web services space. It is intended for the service
customer and provides the information that enables the customer to effectively
use the service and understand how its requests will be processed. In
particular, this includes:
The correct order in which the operations of the service need to be
invoked.
The alternative paths that the execution of the service may follow based
on the received information.
-
The set of steps that represent the possible states in the execution of
the service, which the requester could possibly need to query in the course
of a long-running interaction (as when using a lifecycle inquire
operation; see the section Life Cycle Operations,
Flow Input, and Output).
The data flow between steps, as needed to support the flow of
control.
All this information can be easily encoded through the use of the flow model
described in previous sections. A service description based on a flow model, on
the other hand, does not imply anything about the actual implementation of the
service. Implementation independence is a foremost concern in designing the Web
services framework. Many services are likely to be implemented using
technologies that don't rely on flow models, such as traditional object
oriented languages. Regardless of the implementation technology, these services
require a standards-based description of their behavior to facilitate their use
and integration with other services.
Implementing a Service as a Flow: Private Versus
Public Flows
On the other hand, the language necessary to provide a behavioral description
is fundamentally enough to describe the full execution of that behavior on a
compatible interpreter such as a traditional workflow engine. You just need to
make sure that the language allows the specification of additional
implementation details, such as what program or service to invoke at each
activity in the flow and a set of endpoint and quality-of-service properties
(such as security, transactionality, timing, and so on.) You have already seen
that the WSFL model enables you to do this within the same language that you use
for public flows.
There are two advantages to having a single language for both purposes:
First, a common language enables developers to easily transform existing
business processes (which are commonly encoded as flows) into actual Web
services; second, a flow language capable of encoding actual implementations
defines a platform-independent, standard, portable execution language for Web
services. This implementation language relies on Web service standards
(basically, WSDL and related specifications) to provide implementation details,
and can be executed on any vendor's standardized flow engine.
A flow that provides the service implementation is usually not suitable as a
public description of service behavior; on one hand, it may reveal information
private to the service provider or even trade secrets, whereas on the other
hand, the actual implementation flow is usually too complex and cluttered with
details that have no relevance to customers. To highlight this difference,
it's common to refer to the actual implementation flow as the private
flow of the service, and to its simplified public description as the
public flow.
Defining a Public Flow
The difference between a private flow (one with complete implementation
information) and a simplified (or customer-facing) public flow is thus
fundamentally one of authoring style. Consider now the cell phone ordering
service that has served as an example.
The original process was depicted in Figure
18.5. A simplified flow is shown in Figure
18.6. Here, only the steps that are relevant to the interaction with the
ordering customer are shown. Note, for instance, that the steps of checking
credit history or creating a new account are not present in the simplified flow.
The service user needs to know only that his request will be either rejected
(resulting in a rejection message being sent back to him), or accepted (resulting
in his credit card being charged and a bill sent). Likewise, if you proceed
downstream through the flow, you will see that the activity AssignPhoneNumber
is missing in the public flow, which is explained by the fact that this operation
has internal relevance to the cell phone company but not to the customer.

Figure 18.6
Public flow.
The simplification of the flow is not limited to revealing fewer internal steps
to the customer. First, observe the modification of the control flow, as the
double control dependencies at SendRejection and ChargeCreditCard
are removed. Note also that the relationship established with a shipper service
in activity ShipPhone is not reflected in the flow of Figure
18.6, because this is a private detail that the service does not want to
reveal to customers or competitors. In terms of the definition of the corresponding
activities, you would have in this case an activity without an implementation
block.
Drawing from this example, the typical relationship between the private and
the public flow can be summarized as follows:
Public flows have only a subset of all the activities present in the
private flow. The activities present in the public flow are those needed to
support the proper flow of control and to provide users with information on the
execution state.
Public flows have simpler flow of data and control, but provide full
information about the sequencing of service operations.
The implementation of certain activities is not exposed in public
flows.
A private flow and its corresponding public version both support the same
customer-facing interfaces. From the customer perspective, both flows show the
same service provider type.
Regardless of the differences between a service's private and public
flows, both should match the observable behavior of the service: The same
external interactions with the customer need to be present in both
representations, and the sequencing and control dependencies between them must
be equivalent, in the sense that the two descriptions should accept as valid the
same sequences of message exchanged between a client and the service. Making
sure that this type of equivalence holds can be hard to show in the case of
complex flows. The important point to keep in mind, however, is that from a
service user's perspective, both flows should behave in exactly the same
way.
Global Models
Up until now you've been dealing with the problem of specifying the
behavior of a single Web service, either in executable form (private flow) or as
a public contract (public flow). In practice, every transaction involves at
least two parties, each of which can be characterized in general as a Web
service. Complex transactions can typically involve three and more participants
directly interacting with each other. Using the flow model described in the
previous sections, you can represent the behavior of each one of the parties
involved in a transaction. This, however, is not enough to fully specify how the
interaction is carried out. What is still missing is a specification of the way
in which all these parties need to interact to carry out a certain transaction.
Global models are used in WSFL to specify the form of multiparty
interactions.
To begin, consider the simplest case: an interaction between two services.
A new service must be added to the example, representing an automated cell phone
requester serviceor customerof the ordering service. The customer
service and its interactions with the cell phone order services are shown in
Figure 18.7.

Figure 18.7
Global model involving two parties.
Observe that the customer is modeled as a service itself, with a WSDL
interface and a flow representing its behavior, in just the same way as the
phone ordering service. In non-trivial interactions both the provider and the
requester of a service need to send and receive messages at different points in
their interaction; that is, both effectively behave as clients and servers
simultaneously. The Web services interaction paradigm is thus naturally a
peer-to-peer interaction model.
In WSDL terms, the customer interface includes one notification operation
(sendOrder) and three in-only operations (getRejection,
getInvoice, and getDelivery). The customer's public flow
specifies the steps that need to follow the sending of the order before the
customer's ordering process can be considered terminated: receiving the
bill and receiving a note informing of the phone delivery. The customer can also
receive a rejection message informing it that the request was not accepted.
Plug Links
In addition to the public flows of two services, Figure
18.7 depicts the interactions between the two in the form of connections
between the two services. WSFL refers to these connections as plug links.
Plug links are directional connections that represent the invocation of an operation
of the target service by the source. WSFL models invocations as an ordered pair
consisting of an outbound operation at the source (that is, a WSDL notification
or solicit-response operation) followed by an inbound operation (WSDL one-way
or request-response) at the target.
It is important to note here that WSFL makes the assumption that outbound
operations in a WSDL interface represent a service's ability to invoke the
corresponding inbound operationthat is, one whose signature is obtained by
exchanging the input and output elements in the operation definition. Thus, WSFL
interprets outbound operations by as proxies of the corresponding inbound
operation, and a plug link is basically a symbolic representation of connection
that exists between the proxy and the operation that it actually invokes on a
given service.
The following is an example of a plug link as specified in WSFL syntax:
<plugLink>
<source serviceProvider="customer" portType="customerPortType"
operation="sendOrder"/>
<target serviceProvider="cellPhoneOrderService" portType="orderPortType"
operation="receiveOrder"/>
</plugLink>
In this example, the assumption is that sendOrder and
receiveOrder have dual but matching signatures, as in the sample
portTypes below:
<portType name="customerPortType">
<operation name="sendOrder">
<output message="tns:phoneOrder"/>
</operation>
...
</portType>
<portType name="orderPortType">
<operation name="receiveOrder">
<input message="tns:phoneOrder"/>
</operation>
...
</portType>
Provision must be made, however, for the case in which the types of the messages
sent and received by the source and the target do not match, because in practice
the connected services may have not been developed from a common design. WSFL
allows for simple adaptation of the messages exchanged by means of a mapping
mechanism similar to the one used with data links (see the section Data
Flow). Thus, if the message that sendOrder sends has a different
type from the message that receiveOrder accepts, a map specification
can be included in the plug link to provide for the necessary data mapping:
<plugLink>
<source serviceProvider="customer" portType="customerPortType"
operation="sendOrder"/>
<target serviceProvider="cellPhoneOrderService" portType="orderPortType"
operation="receiveOrder"/>
<map sourceMessage="sendOrderOutput" sourcePart="personalInfo"
targetMessage="receiveOrderInput" targetPart="customerData"/>
</plugLink>
Global Models in WSFL
To describe a multiparty transaction, WSFL uses a new construct: the global
model. A global model identifies the set of service instances that participate
in the transaction (these are the service providers you saw in the section Flows
as Compositions of Web Services) and uses plug links to define the
interactions between them.
The customer-to-phone order service transaction has a very simple global
model with two providers and four plug links:
<globalModel name="phoneOrder">
<serviceProvider name="customer"
serviceProviderType="abc:customerType"/>
<serviceProvider name="cellPhoneOrderService"
serviceProviderType="cde:phoneOrderType"/>
<plugLink>
<source serviceProvider="customer" portType="abc:customerPortType"
operation="sendOrder"/>
<target serviceProvider="cellPhoneOrderService"
portType="cde:orderPortType" operation="receiveOrder"/>
</plugLink>
<plugLink>
<source serviceProvider="cellPhoneOrderService"
portType="cde:orderPortType" operation="rejectOrder"/>
<target serviceProvider="customer" portType="abc:customerPortType"
operation="getRejection"/>
<map ... />
</plugLink>
<!-- Additional plug links here -->
...
</globalModel>
Service providers (or service instances) identify a particular usage of a certain
service, as opposed to the service itself. Service instances are typed according
to a service type (a named set of WSDL interfaces, see Flows
as Compositions of Web Services), and they are assigned a unique name
within the global model. Plug links simply identify the source and target providers
by their names, and the operations within those providers that are involved
in the interaction.
Clearly, global models need not be limited to two-party interactions. Figure
18.8 shows a modification of the two-party phone order global model in which
the order service has outsourced all the shipping functions to a third shipping
service. The interaction between the customer and the phone ordering service
is now limited to the initial ordering and billing. Both the phone ordering
service and the customer have direct interactions with the shipping service:
The phone ordering service transmits the phone shipment request to the shipper
and lets it deal with all the shipping-related functions; the customer receives
the delivery information directly from the shipper.

Figure 18.8
Global model involving three parties.
In the corresponding global model, there are three providers and three groups
of plug links representing the interactions between them. You can see in the
following example that the three service providers
("customer" on the left of the figure,
"cellPhoneOrderService" in the middle, and
"shipper" on the right) are declared at the top of the XML
coding of the global model. In the rest of the global model, the customer to
phone ordering service, phone ordering service to shipper, and shipper to
customer interactions are defined in the form of sets of plug links connecting
each pair of service providers. All possible pair-wise interactions between the
providers are represented in the global model:
<globalModel name="phoneOrder">
<serviceProvider name="customer"
serviceProviderType="abc:customerType"/>
<serviceProvider name="cellPhoneOrderService"
serviceProviderType="cde:noShipperPhoneOrderType"/>
<serviceProvider name="shipper"
serviceProviderType="cde:shipperType"/>
<!-- customer to phone order service links -->
<plugLink>
<source serviceProvider="customer" portType="abc:customerPortType"
operation="sendOrder"/>
<target serviceProvider="cellPhoneOrderService"
portType="cde:orderPortType" operation="receiveOrder"/>
</plugLink>
...
<!-- phone order service to shipper link -->
<plugLink>
<source serviceProvider="cellPhoneOrderService" portType="cde:porderPortType"
operation="sendOrder"/>
<target serviceProvider="shipper"
portType="fgh:shipperPortType" operation="receiveShippingOrder"/>
</plugLink>
<!-- shipper to customer link -->
<plugLink>
<source serviceProvider="shipper" portType="fgh:shipperPortType"
operation="deliveryNote"/>
<target serviceProvider="customer"
portType="abc:customerPortType" operation="getDelivery"/>
</plugLink>
</globalModel>
This example illustrates the distributed nature of the information that a global
model is designed to capture. Note that in this case no single party has a complete
view of the global interaction. The global transaction is a distributed composition
in which two or more service providers are connected according to a certain
interaction pattern to enable a level of functionality (a business goal) not
provided by any service independently. Compare this form of composition with
the type of compositions created when you use flows to define usage patterns
of services, as described in Flows as Compositions
of Web Services.
References
For more information on the topics discussed in this chapter, see these
references:
Summary
This chapter reviewed the basic concepts of Web services flow languages,
using WSFL as a model. Flow languages, and the fundamental notions of flows and
compositions of Web services, are the basic pieces required to support complex,
multiparty, and long- running service interactions, such as the ones involved in
any realistic business-to-business transaction.
Authors of this Chapter
Francisco Curbera holds a Ph.D. in Computer Science from Columbia University, and is currently a Research Staff Member at IBM's T.J. Watson Research Center. He has worked for several years on the use of markup languages for application development and composition of software components, including the definition of the Bean Markup Language (BML), and the design of algorithms for managing XML documents. More recently, he has been involved in the definition and implementation of several Web services specifications. He is one of the authors of the Web Services Description Language (WSDL) and of the Web Services Flow Language (WSFL).
Matthias Kloppmann is a Senior Software Engineer with IBM Software Group's lab in Bvblingen, Germany. He holds an M.S. in Computer Science and Electrical Engineering from the University of Stuttgart. Matthias has many years of experience with building workflow systems, both in C++ and, more recently, in Java. He has participated in the creation of WSFL, the Web Services Flow Language, and the design of the XML and Web services extensions for MQSeries Workflow. Currently, Matthias is working as a workflow architect on WebSphere, IBM's J2EE application server.
Source of this material
 |
This is Chapter 18: Web Services and Flows (WSFL) from the book Java Web Services Unleashed (ISBN:0-672-32363-X) written by Robert Brunner, Frank Cohen, Francisco Curbera, Darren Govoni, Steve Haines, Matthias Kloppmann, Ben Marchal, Scott Morrison, Arthur Ryman, Joe Weber, and Mark Wutka, published by Sams Publishing.
© Copyright Pearson Education. All rights reserved. |
To access the full Table of Contents for the book