15. WS-BPEL
Abstract Processes
<insert 82 base
text >
…
15.3
Abstract Process Profile for Observable Behavior
Motivation
The
objective of the Abstract Process Profile for Observable Behavior is to provide
precise and predictable descriptions of observable service behavior. The main
application of this profile is the definition of business protocols, that is,
the protocol followed by one business partner in the context of a Web services
exchange. Business protocols are particularly relevant in automated
cross-enterprise interactions, including business-the area e-commerce, but have
general applicability in the extension of service contracts with precise,
machine processable behavioral descriptions.
There
several a key differences between processes intended to represent business
protocols and fully executable processes. Foremost among them is the different
way in which data are handled in each case; the rich data manipulation that
occurs in executable processes need not be described in public protocols.
Instead, public protocols use non-deterministic data values to hide the private
aspects of executable behavior. For example, using opaque assignment supports modeling the
non-deterministic effects that private computation has on external behavior.
In
this profile, the use of opacity is consequently concentrated in those features
associated with data handling. Non-deterministic data values are not allowed in
executable processes;
abstract processes, on the other hand, use non-deterministic
values to reflect the consequences of actual behavior while maintaining the
details of that behavior private.
Profile
URI
The
URI identifying this abstract process profile is:
urn:oasis:names:tc:wsbpel:2.0:abstract:ap11<year><month>
Subset
of the Processes Allowed in the Base
This
profile is concerned mainly with hiding internal processing of a business
partner while capturing all the information required to
describe how the process interacts with its partners. The set of usage
restrictions associated with the use of abstract processes in general was in
fact derived from this original requirement, which was captured by the Abstract
Process definition incorporated in the previous version of this specification
(BPEL4WS V1.1, May 2003).
It
has been mentioned already that this profile applies opacity in BPEL constructs
that handle data. In addition, opaque tokens are allowed to be omitted using
the omission-shortcut described in section 15.
The
profile described here allows the use of opaque activities for supporting two
specific tasks. First is the hiding of a non-opaque activity that is the source
or target of one or more links in an executable process from which a business protocol
is defined, while maintaining the same flow of control in the abstract
representation. Second, is the use of the omission shortcut in places where an
activity is required by the BPEL semantics and schema (e.g., activity in a
fault handler; this usage obviates the way instead of requiring one to add an
<empty> just to satisfy the schema). The use of opaque activities
elsewhere is superfluous, because this profile’s completion rules are
flexible about where one can add an activity in an executable completion. The
full completion rules are presented in the next section.
This
profile restricts the use of the Abstract Process Base in the following manner:
- Expressions:
joinCondition is not allowed to be opaque. The joinCondition is based on the transition conditions of
the incoming links, with a default value being the disjunction of the
status of those links, and not on data handled by the process. Therefore, it is not appropriate to hide
it. Other expressions may be opaque, as defined in section 15.
- Activities:
The use of <exit > is not allowed.
- Attributes: Only the attributes used for
identification of data containers of activities representing partner interactions
are allowed to be opaque. Note that assigning to opaque containers is already
available using the opaque assignment capability discussed in section 15,
where one assigns from an opaque expression. The full list of the
attributes allowed to be opaque is shown below. The following is the
complete list of attributes, belonging to the receive, invoke, reply, onMessage, or onEvent
constructs, that are allowed to be opaque in this profile:
- "variable",
"inputVariable", "outputVariable",
- "part"
and "toVariable" attributes of the "fromPart"
element,
- "part"
and "fromVariable" attribute of
"toPart"
The level of abstraction appropriate in
the description of business protocols makes it often unnecessary to use message
variables in Web service interaction activities, particularly when the intent is
to simply constrain the sequencing of such activities and the actual message
data is not relevant.
Subset
of the Executable Completions Allowed in the Base
With
respect to executable BPEL completions of an abstract process that uses this
profile, the intent of the profile requires a valid completion to follow the
same interactions as the abstract process, with the partners that are specified
by the abstract process. The executable process may, however, perform
additional interaction steps relating to other partners.
Therefore:
a completion MUST NOT change the presence or order of interactions already in
the abstract process, and it MUST NOT perform additional interactions with the
partner links defined in the abstract process. It is important to observe that
one way in which the order of interactions can be modified is by changing the
value of a variable used in a condition that affects branching in such a way
that the new effective branching behavior is in direct conflict with what is
specified by the abstract process. Conditions that affect the flow of control
such as transition conditions, “if-then” or “while”
expressions, among others, can have such an effect on the order of
interactions. In this profile, we will not restrict writing to variables in a
strict manner, but provide this note as an advisory restriction.
The
possible locations of new activities are not explicitly defined in this
profile. Activities may be added anywhere where completions to the base are
allowed, as long as the restrictions enumerated below are followed. In this
profile, the valid executable completions of an abstract process are obtained
through both 'opaque token replacement' and 'addition of BPEL constructs', with
the following restrictions:
- New
activities (including those created to replace opaque activities) MUST NOT
interact with partnerLinks already defined in
the abstract process. This rule does not affect adding interactions with
new partnerLinks present in the executable
completion but not in the abstract process.
- It is
not allowed to modify (in an <assign> activity or otherwise) the
endpoint reference of a partnerLinks defined in
the abstract process, because that would effectively prevent subsequent
interactions with that partner.
Remember that 'opaque token replacement' also replaces opaque
tokens omitted through the omission-shortcut.
- The
lexical parent an existing BPEL construct (including activities in
particular) present in the abstract process MUST NOT be
changed in a valid executable completion. Hence, the nesting structure of
composite activities around any activity in an abstract process MUST
remain unchanged in any legal completion. Some examples to illustrate this
restriction are provided below. The word ‘existing’ is used in
the examples to refer to constructs defined in the abstract process from
which the executable completions are being created:
- Examples
of legal additions:
- Adding
a variable or a partner link to an existing scope S, even though that
scope is the parent of existing activity A.
- Adding
a new link def to an existing flow.
- Examples
of illegal additions:
- Adding
a <while> activity around the existing activity A whose parent is
another existing activity B.
- Adding
a new scope around an existing variable definition whose parent is an
existing scope S.
- A
valid executable completion MUST NOT add:
- New
branches to an existing “if-then-else” activity, unless it
has no “else” branch, and the new branch is added after all
existing branches.
- New
branches to an existing pick activity.
- New
fault, compensation, or termination handlers to an existing scope.
However, they may be added at the process level.
- <exit> activities.
- Activities
that throw non-standard faults MAY be added only if the exception will not
be propagated outside of the highest newly
added ancestor of the fault-throwing activity. For example, consider adding an activity
A as a child of an existing sequence S.
Then, one may only add a <throw> within A if the fault it
throws does not reach the scope of the existing sequence S. In other
words, the fault must be caught and fully handled by A or its descendants, and not be re-thrown by them.
Observe
that executable completions MUST NOT add new links targeting an activity that
exists in the abstract process. Adding such a new link would have the effect of
changing the corresponding join condition, which is in violation of the
completion rules of the base (since it modifies a non-opaque existing value).
This restriction does not affect the addition of links to new activities that
are not replacing opaque activities.
Clarification
on the use of Opaque Variable References
Unlike executable processes, variables in
abstract processes defined using this profile do not need to be fully initialized
before being used since additional computation may be implicitly assumed.
However, since message properties are meant to represent
"transparent", or protocol relevant, data all message properties in a
message MUST be initialized before the message can be used. In particular, all
properties in a message need to be initialized before a variable containing the
message is used as the inputVariable in a Web service invocation.
This section clarifies the meaning of
using opacity of variables in interaction activities. If no variable is
specified in an interaction activity which receives an incoming message, then
the abstract process MUST NOT subsequently refer to the received message or its
properties, if any. If the variable reference is omitted for an activity that
sends an outgoing message, then any properties of the message are considered to
have been initialized through opaque assignment,
When variable references are omitted in
interaction activities, correlation set references may be interpreted as
follows:
- When an incoming message initializes
a correlation set (initiator case), the correlation set is considered to
be initialized.
- When an outgoing message initializes
a correlation set (initiator case), the correlation tokens (message
properties) are initialized through an implicit opaque assignment.
- For an outgoing message which
references but does not initialize a correlation set (follower case), the
proper initialization of the message properties is implicit. In this case,
the already initialized correlation set itself provides the token values
for the outgoing message.
It is not possible to arbitrarily mix
interaction activities that use variable references with those that
don’t. If a correlation set is initialized by rules 1 or 2 above, then
outgoing messages using the same correlation set MUST also refrain from
referencing a message variable. This restriction applies because it is not
possible to initialize the properties of the outgoing messages from the
correlation set alone.
16. Examples
16.1. Shipping
Service: Abstract Process, Observable Behavior Profile
This example presents the use of a WS-BPEL
abstract process to describe a rudimentary shipping service. This service handles
the shipment of orders. From the service point of view, orders are composed of
a number of items. The shipping service offers two types of shipment: shipments
where the items are held and shipped together and shipments where the items are
shipped piecemeal until all of the order is accounted for.
16.1.1. Service
Description
The context for the shipping service is a
two-party interaction between a customer and the service. This is modeled in
the following partnerLinkType
definition:
<plnk:partnerLinkType name="shippingLT">
<plnk:role name="shippingService"
portType ="shippingServicePT"/>
<plnk:role name="shippingServiceCustomer">
portType ="shippingServiceCustomerPT"/>
</plnk:partnerLinkType>
The corresponding message and portType
definitions are as follows:
<wsdl:definitions
targetNameSpace="http://ship.org/wsdl/shipping"
xmlns:ship= ...>
<! -- import ship schema -- >
<message name="shippingRequestMsg">
<part name="shipOrder" type="ship:shipOrder"/>
</message>
<message name="shippingNoticeMsg">
<part name="shipNotice" type="ship:shipNotice"/>
</message>
<portType name="shippingServicePT">
<operation name="shippingRequest">
<input message="shippingRequestMsg"/>
</operation>
</portType>
<portType name="shippingServiceCustomerPT">
<operation name="shippingNotice">
<input message="shippingNoticeMsg"/>
</operation>
</portType>
</wsdl:definitions>
16.1.2. Message
Properties
The properties relevant to the service
behavior are:
·
The ship order ID that is
used to correlate the ship notice(s) with the ship order (shipOrderID)
·
Whether the order is to be
shipped complete or not (shipComplete)
·
The total number of items in
the order (itemsTotal)
·
The number of items referred
to in a ship notice so that, when partial shipments are acceptable, we can use
this, along with itemsTotal, to track
the overall fulfillment of the shipment (itemsCount)
Here are the definitions for the
properties and their aliases:
<wsdl:definitions
targetNamespace="http://example.com/shipProps/"
xmlns:sns="http://ship.org/wsdl/shipping"
xmlns:ship = “http://example.com/ship.xsd”>
<!-- types used in abstract processes are required to be finite domains.
The itemCountType is restricted by range -->
<wsdl:types>
<xsd:schema targetNamespace=“http://example.com/ship.xsd”>
<xsd:simpleType name="itemCountType">
<xsd:restriction base="xsd:int">
<xsd:minInclusive value="1"/>
<xsd:maxInclusive value="50"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
</wsdl:types>
<bpws:property name="shipOrderID" type="xsd:int"/>
<bpws:property name="shipComplete" type="xsd:boolean"/>
<bpws:property name="itemsTotal" type="ship:itemCountType"/>
<bpws:property name="itemsCount" type="ship:itemCountType"/>
<bpws:property name="numItemsShipped"
type="ship:itemCountType"/>
<bpws:propertyAlias propertyName="tns:shipOrderID"
messageType="sns:shippingRequestMsg"
part="shipOrder">
<query>
ShipOrderRequestHeader/shipOrderID
</query>
</bpws:propertyAlias>
<bpws:propertyAlias propertyName="tns:shipOrderID"
messageType="sns:shippingNoticeMsg"
part="shipNotice">
<query>
ShipNoticeHeader/shipOrderID
</query>
</bpws:propertyAlias>
<bpws:propertyAlias propertyName="tns:shipComplete"
messageType="sns:shippingRequestMsg"
part="shipOrder">
<query>
ShipOrderRequestHeader/shipComplete
</query>
</bpws:propertyAlias>
<bpws:propertyAlias propertyName="tns:itemsTotal"
messageType="sns:shippingRequestMsg"
part="shipOrder">
<query>
ShipOrderRequestHeader/itemsTotal
</query>
</bpws:propertyAlias>
<bpws:propertyAlias propertyName="tns:itemsCount"
messageType="sns:shippingNoticeMsg"
part="shipNotice">
<query>
ShipNoticeHeader/itemsCount
</query>
</bpws:propertyAlias>
</wsdl:definitions>
16.1.3. Process
Next is the process definition. For
brevity, the abstract process definition does not include, for example, the
handling of error conditions (business or otherwise) that a complete
description would account for. The rough outline of the process is as follows:
receive shipOrder
if
condition shipComplete
send shipNotice
else
itemsShipped := 0
while itemsShipped < itemsTotal
itemsCount := opaque // non-deterministic assignment
// corresponding e.g. to
// internal interaction with
// back-end system
send shipNotice
itemsShipped = itemsShipped + itemsCount
And here is the more complete version:
<process name="shippingService"
targetNamespace="http://acme.com/shipping"
xmlns="http://schemas.xmlsoap.org/ws/2004/03/business-process/"
xmlns:sns="http://ship.org/wsdl/shipping"
xmlns:props="http://example.com/shipProps/" abstractProcessProfile="urn:oasis:names:tc:wsbpel:2.0:abstract:ap11<year><month>
">
<partnerLinks>
<partnerLink name="customer" partnerLinkType="sns:shippingLT"
partnerRole="shippingServiceCustomer"
myRole="shippingService"/>
</partnerLinks>
<variables>
<variable name="shipRequest" messageType="sns:shippingRequestMsg"/>
<variable name="shipNotice" messageType="sns:shippingNoticeMsg"/>
<variable name="itemsShipped" type="props:itemCountType"/>
</variables>
<correlationSets>
<correlationSet name="shipOrder" properties="props:shipOrderID"/>
</correlationSets>
<sequence>
<receive partnerLink="customer" portType="sns:shippingServicePT"
operation="shippingRequest"
variable="shipRequest">
<correlations>
<correlation set="shipOrder" initiate="yes"/>
</correlations>
</receive>
<if>
<condition>
bpws:getVariableProperty('shipRequest','props:shipComplete')
</condition>
<then>
<sequence>
<assign>
<copy>
<from variable="shipRequest"
property="props:itemsCount"/>
<to variable="shipNotice"
property="props:itemsCount"/>
</copy>
</assign>
<invoke partnerLink="customer"
portType="sns:shippingServiceCustomerPT"
operation="shippingNotice"
inputVariable="shipNotice">
<correlations>
<correlation set="shipOrder" pattern="out"/>
</correlations>
</invoke>
</sequence>
</then>
<else>
<sequence>
<assign>
<copy>
<from>0</from>
<to>$itemsShipped</to>
</copy>
</assign>
<while>
<condition>
$itemsShipped <
bpws:getVariableProperty('shipRequest','props:itemsTotal')
</condition>
<sequence>
<assign>
<copy>
<from opaque="yes"/>
<to variable="shipNotice"
property="props:itemsCount"/>
</copy>
</assign>
<invoke partnerLink="customer"
portType="sns:shippingServiceCustomerPT"
operation="shippingNotice"
inputVariable="shipNotice">
<correlations>
<correlation set="shipOrder"
pattern="out"/>
</correlations>
</invoke>
<assign>
<copy>
<from>
$itemsShipped
+
bpws:getVariableProperty('shipNotice',
'props:itemsCount')
</from>
<to>$itemsShipped</to>
</copy>
</assign>
</sequence>
</while>
</sequence>
</else>
</if>
</sequence>
</process>