[Editor's Note: This article is a programming example that illustrates the features of the Web Services Flow Language. It assumes that you already know the basic concepts behind workflow and WSFL. If you need a refresher, please see the Resources section for a selection of overview articles on WSFL.]
Let's imagine that Strong.com acts as a brokerage and hosts a Web service which manages client financial accounts. Additionally consider that the New York Stock Exchange (NYSE) hosts a Web service that allows traders to buy and sell stocks just as if they were on the trading floor. Strong.com realizes that they can provide a compelling service to their end users if they integrate these Web services together.
When clients request stock purchases from the brokerage service, it kicks off a business process that first checks the real-time stock quote service from our fictional service provider StockQuote.com, to determine the stock price. After determining the stock price, the total price of the transaction may be computed based on the number of shares requested. Strong.com's account manager Web service will determine if the client has enough funds to cover the transaction. After successfully verifying the client's ability to purchase the stock, the trade is executed by invoking the NYSE's virtual trading floor Web service.
Thus, Strong.com will define a new stock-trading Web service by integrating its account manager service with StockQuote.com's stock quote service and the NYSE's virtual trading floor Web service. This programmatic integration of remote Web services into a single Web service is accomplished by defining the sequencing and integration of Web service operations within a WSFL flow.
Figure 1: WSDL-defined operations for services from StockQuote.com, NYSE.com and Strong.com

Figure 1 illustrates that Strong.Com is hosting an
accountManagement Web service that implements a
checkCredit operation. The NYSE.com service provider
is hosting a VirtualTradingFloor Web service with a
purchaseStockBlock operation. Finally, the
Stock.Quote.com service provider is hosting an RTStockQuote Web service,
that implements a getStockPrice operation.
The RTStockQuote Web service leverages the
StockQuoteServiceImpl_Service portType as defined in
Listing 1.
Listing 1: RTStockQuote's portType implementation
<message name="IngetStockPriceRequest">
<part name="meth1_inType1" type="xsd:string"/>
</message>
<message name="OutgetStockPriceResponse">
<part name="meth1_outType" type="xsd:float"/>
</message>
<portType name="StockQuoteServiceImpl_Service">
<operation name="getStockPrice">
<input message="InGetStockPriceRequest"/>
<output message="OutGetStockPriceResponse"/>
</operation>
</portType>
|
The getStockPrice operation accepts a
string parameter representing a stock symbol and returns a float value
indicating the stock price.
The accountManagement Web service has the WSDL
description in Listing 2 for the checkCredit operation.
Listing 2: WSDL for the accountManagement service
<message name="InCheckCreditRequest">
<part name="clientID" type="xsd:long"/>
<part name="stockPrice" type="xsd:int"/>
<part name="quantity" type="xsd:int"/>
</message>
<message name="OutCheckCreditResponse">
<part name="response" xsd:type="xsd:boolean"/>
</message>
<portType name="AccountManagementPT">
...
<operation name="checkCredit">
<input message="InCheckCreditRequest"/>
<output message="OutCheckCreditResponse"/>
</operation>
...
</portType>
|
The checkCredit operation accepts three
parameters including the client id, stock price, and number of shares
requested. The cost of the entire transaction is computed and compared
against the client's assets. The return value is a Boolean indicating
whether the client's current standing allows for this stock trade. The
purchaseStockBlock operation has the
description shown in Listing 3.
Listing 3: purchaseStockBlock's description
<message name="InPurchaseStockBlockRequest">
<part name="symbol" type="xsd:string"/>
<part name="shareCount" type="xsd:int"/>
</message>
<message name="OutPurchaseStockBlockResponse">
<part name="result" type="xsd:boolean"/>
</message>
<portType name="MarketExchangePT">
<operation name="purchaseStockBlock">
<input message="InPurchaseStockBlockRequest"/>
<output message="OutPurchaseStockBlockResponse"/>
</operation>
</portType>
|
The purchaseStockBlock operation accepts two
string arguments indicating the stock symbol and number of shares
requested for purchase. The result is a Boolean value indicating whether
the trade was executed successfully.
To define a Web service as an aggregation of other services, WSFL descriptions fall in to one of two categories:
- Define the execution sequence of Web service operations
- Map the operations of the aggregate Web service to operations implemented by the contained Web services
The first class of descriptions is contained within a WSFL flow model.
The flow model defines a series of activities that represent
operations of the aggregate Web service, and specifies the order of
execution for those activities. The flow model represents the aggregate
Web service by defining a public interface or portType of operations. You
can think of it as representing a directed graph of the Web service
interactions defining the aggregate Web service.
Figure 2: Directed graph for StockPurchaseFlow service

Figure 2 is a directed graph that defines the activities or
tasks that are implemented in our new Web service that
allows users to purchase stock. The StockPurchaseFlow Web service
is actually tying the Web services implemented by Strong.Com, NYSE.com,
and StockQuote.com together by leveraging WSFL.
Activities represent single stages or tasks within the flow. The arrows
represent edges of the directed graph and indicate the order in which
activities are executed. Thus in our example, the StockPurchaseFlow
Web service, when invoked, will retrieve the stock quote before checking
the requester's credit. After verifying that the client has the ability to
purchase the stock, the Web service will actually execute the stock trade.
Each individual task is implemented by a separate Web service, while a
WSFL service provider implements the operations of the aggregate Web
service.
In Figure 2, NYSE_VirtualTradingFloor,
RealTimeStockQuoteProvider, and and
StrongStockPortfolioManager are service providers which implement
the specified activities as Web service operations.
The WSFL flow model definition in Listing 4 corresponds to the directed graph in Figure 2.
Listing 4: The WSFL flow model
<flowModel name="StrongStockPurchaseFlow"
serviceProviderType="StockPuchaseFlow">
<serviceProvider name="NYSE_VirtualTradingFloor" type="VirtualTradingFloor">
<locator type="static" service="nyse.com/vtf.wsdl"/>
</serviceProvider>
<serviceProvider name="StockQuoteRealTimeStockQuoteProvider"
type="RealTimeStockQuoteProvider">
<locator type="uddi" bindTime="startup" selectionPolicy="first">
<uddi-api:find_service businessKey="uuid_key" generic="1.0"
xmlns:uddi-api="urn:uddi-org:api">.
<tModelBag>
<tModelKey>
UUID:C1ACF26D-9672-4404-9D70-39B756E62AB4
</tModelKey>
</tModelBag>
</uddi-api:find_service>
</locator>
</serviceProvider>
<serviceProvider name="StrongAccountManager" type="AccountManager">
<locator type="static"
service="Strong.com/stockquoteserviceimpl_service-interface.wsdl"/>
</serviceProvider>
<activity name="retrieveStockQuote">
<performedBy serviceProvider="StockQuoteRealTimeStockQuoteProvider"/>
<implement>
<export>
<target portType="StockPortfolioTrackerPT"
operation="retrieveStockQuote"/>
</export>
</implement>
</activity>
<activity name="creditCheck">
<performedBy serviceProvider="StrongAccountManager"/>
<implement>
<export>
<target portType="StockPortfolioTrackerPT"
operation="verifyCredit"/>
</export>
</implement>
</activity>
<activity name="executeTrade">
<performedBy serviceProvider="NYSE_VirtualTradingFloor"/>
<implement>
<export>
<target portType="StockPortfolioTrackerPT" operation="bid"/>
</export>
</implement>
</activity>
<controlLink source="retrieveStockQuote" target="creditCheck"/>
<controlLink source="creditCheck" target="executeTrade"
transitionCondition="OutCheckCreditResponse/response"/>
<dataLink name="dataLink0" source="flowSource" target="retrieveStockQuote">
<map sourceMessage="InPurchaseStockRequest"
targetMessage="InRetrieveStockQuoteRequest"
sourcePart="stockSymbol" targetPart="meth1_inType1"/>
</dataLink>
<dataLink name="dataLink1" source="flowSource" target="creditCheck">
<map sourceMessage="InPurchaseStockRequest"
targetMessage="InCheckCreditRequest"
sourcePart="clientID" targetPart="clientID"/>
<map sourceMessage="InPurchaseStockRequest"
targetMessage="InCheckCreditRequest"
sourcePart="numOfShares" targetPart="quantity"/>
</dataLink>
<dataLink name="dataLink2" source="retrieveStockQuote" target="creditCheck">
<map sourceMessage="OutRetrieveStockQuoteResponse"
targetMessage="InCheckCreditRequest"
sourcePart="meth1_outType" targetPart="stockPrice"/>
</dataLink>
<dataLink name="dataLink3" source="flowSource" target="executeTrade">
<map sourceMessage="InPurchaseStockRequest"
targetMessage="InBidRequest"
sourcePart="stockSymbol" targetPart="symbol"/>
<map sourceMessage="InPurchaseStockRequest"
targetMessage="InBidRequest"
sourcePart="numOfShares" targetPart="shareCount"/>
<dataLink>
<dataLink name="dataLink4" source="executeTrade" target="flowSink">
<map sourceMessage="OutBidResponse" ="OutPurchaseStockResponse"
sourcePart="result" targetPart="sucessfulTrade"/>
</dataLink>
</flowModel>
|
Before we step through this flow model, let's revisit what the flow model represents.
Remember that we are defining a new Web service as an aggregation of other Web services. The aggregate Web service will have operations and accept incoming messages while generating output messages, just as any other Web service would. The aggregate Web service exposes operations as activities that are implemented by other Web services. The sequence in which activities are executed must be defined. Furthermore, we must also define bindings from the aggregate Web services operations to the original Web services operations. The flow model defines how input messages to the aggregate Web service are mapped to inputs to the activities. It also defines the sequence of execution for activities and the data flow between activities. However, the flow model does not define how the aggregate Web service activities and operations are bound to the underlying Web services. Instead, the WSFL global model takes care of this for us.
For now, we will discuss the aggregate Web service -- which is defined by the flow model -- and will leave a discussion of the global model for part two of this series..
The notion of a service provider is a new concept, relative to the other Web service technologies we have investigated thus far. A service provider is an entity which hosts Web services and which thus provides implementations for Web service operations.
You can think of a service provider is a being analogous to a
UDDI businessEntity. A service provider type is simply a collection
of WSDL portTypes that service providers of that type support. When we
define our flow model, we are actually creating a new service provider
type. Thus we are defining the public interface to a Web service:
<flowModel name="StrongStockPurchaseFlow" serviceProviderType="StockPuchaseFlow"> ... </flowModel> |
The flow model document element is flowModel and specifies a
name for the flow (i.e. StrongStockPurchaseFlow) along with defining the
service provider type that is defined by the flow model (i.e. StockPurchaseFlow).
We then proceed to declare the service providers (see Listing 5), which will be referenced within the flow.
Listing 5: Declaring the service providers
<serviceProvider name="NYSE_VirtualTradingFloor" type="VirtualTradingFloor">
<locator type="static" service="nyse.com/vtf.wsdl"/>
</serviceProvider>
<serviceProvider name="StockQuoteRealTimeStockQuoteProvider"
type="RealTimeStockQuoteProvider">
<locator type="uddi" bindTime="startup" selectionPolicy="first">
<uddi-api:find_service businessKey="uuid_key"
generic="1.0" xmlns:uddi-api="urn:uddi-org:api">
<tModelBag>
<tModelKey>
UUID:C1ACF26D-9672-4404-9D70-39B756E62AB4
</tModelKey>
</tModelBag>
</uddi-api:find_service>
</locator>
</serviceProvider>
<serviceProvider name="StrongAccountManager" type="AccountManager">
<locator type="static"
service="Strong.com/stockquoteserviceimpl_service-interface.wsdl"/>
</serviceProvider>
|
Remember that we intend to leverage three Web services hosted by NYSE.com,
StockQuote.com, and Strong.com. We identify the service providers with the
serviceProvider element that supports a name attribute so
that we may refer to the service provider later in the document. As well,
the serviceProvider element supports a type attribute that
indicates the service provider type implemented by the service provider.
The locator element identifies a WSDL service implementing the
service provider type. WSDL services may be located statically or
dynamically. The locator element supports the following type bindings:
- static : The specific service implementation is specified via the service attribute, which references a WSDL or WSFL definition of the service.
- local : The specific service implementation is local (e.g. Java object) and may be referenced via an application-specific means.
-
uddi : The service implementation is discovered
leveraging the UDDI SOAP inquiry API. We published our stock quote
service earlier, so we search based on the registered tModelKey.
The
bindTimeattribute indicates when the service implementation is located and bound. The following values are supported:- startup : The service is bound when the flow model is instantiated.
- firstHit : The service is located and bound via UDDI the first time an activity implemented by the service provider is invoked.
- deployment : The service is bound when the flow model is deployed.
selectionPolicydefines how a service provider is selected if the UDDI query returns more than one service implementation. The following values are supported:- first : The first service is selected from the result set
- random : A random service is selected from the result set
-
user-defined : A user-defined selection policy is invoked:
<locator type="uddi" bindTime="firstHit" selectionPolicy="user-defined" invoke="mySelectionPolicy.exe"/>
-
mobility
The service provider is referenced in a message generated by an activity within the flow:<locator type="mobility" activity="processMarketRequest" message="InGetStockQuoteInMarket" messagePart="marketID" dataField="providerInfo"/>
The processMarketRequest activity generates an InGetStockQuoteInMarket message as output which contains the marketID along with a providerInfo data field which contains the binding information for the service provider -
any
The service provider is not restricted in any way by the flow model. This enables the condition where a third party instantiates the flow and defines the service provider who implements the referenced activities at that time.
After defining the service providers, we specify the activities which the aggregate service implements:
<activity name="retrieveStockQuote">
<performedBy serviceProvider="StockQuoteRealTimeStockQuoteProvider"/>
<implement>
<export>
<target portType="StockPortfolioTrackerPT"
operation="retrieveStockQuote"/>
</export>
</implement>
</activity>
|
The activity element is used to define an activity. The
StockQuoteRealTimeStockQuoteProvider, as indicated by the
performedBy element, implements the retrieveStockQuote
activity. The public interface for the flow model exposes the
retrieveStockQuote activity as an operation. Thus a WSDL description of
the aggregate service may be generated which identifies the input and
output messages for the retrieveStockQuote operation which is exported.
The retrieveStockQuote operation will be contained within the
StockPortfolioTrackerPT portType.
The creditCheck activity is performed by the
StrongAccountManager service provider and is exposed as the
verifyCredit operation within the StockPortfolioTrackerPT portType.
The executeTrade activity is implemented by the
NYSE_VirtualTradingFloor service provider and is implemented by the
aggregate service with the bid operation, which is defined within
the StockPortfolioTrackerPT portType.
Activities may have exit conditions defined. The exitCondition
element defines a Boolean expression, which is evaluated when an activity
completes its operation. The expression may reference input and output
messages of the current activity, or of activities executed prior to the
current activity. If the expression evaluates to true, the activity
terminates gracefully and yields execution to a subsequent activity. If
the expression evaluates to false, the activity is invoked again. Thus
exit conditions allow for loops within the flow. The directed graph
defined by a flow model must be acyclic, and may not contain loops.
However, a specific activity may support multiple subsequent iterations by
leveraging exit conditions:
Ex: <activity name="buyStockAtGivenPrice" ExitCondition="OutGetStockPriceResponse.meth1_outType <= InPurchaseStockRequest.desiredPrice"/> |
I pause here for a moment since this is quite enough information to soak in all at the same time. This part identified the many activities needed by our flow model for Strong.com. In the next part we will look into how to link together these activities and complete the flow.
-
For more info, read Programming Web Services with Java
, Ajamu Wesley, Manning Publications, 2002. ISBN 1930110421
- See the XML Cover Pages on the Web Services Flow Language (WSFL).
- Check out ebPML on WSFL.
- See
Going With the Flow
, Intelligent Enterprise Magazine feature article about WSFL, September 2001.
- Read the Web Services Overview (in PDF).
- And The WSFL specification (in PDF).
- Download the IBM alphaWorks Web Service Process Management Toolkit.
- See also the Oasis Web Service Component Model (WSCM).
Ajamu Wesley is a Senior Architect within IBM's Emerging Internet Technology division. Ajamu develops technical strategy, and architecture while providing technical consulting services promoting the adoption of leading edge technologies. His current role is technical lead for Federated Identity. Ajamu has generated several external technical publications with his latest project being the authorship of "Programming WebServices", which is an instructive book for programmers focusing on WebServices and related technologies. He can be reached at awesley@us.ibm.com.




