Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

WSFL in action, Part 1

When Web services cooperate

Ajamu Wesley (awesley@us.ibm.com), Senior software architect, IBM Software Group
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.

Summary:  This article is based upon a chapter from "Programming Web Services with Java" (Manning, 2002) that explains how you can use the flexible Web Services Flow Language (WSFL) to create new Web services by integrating other Web services. This is the first of a two part series with a detailed example of how several Web services from different service providers can work in a flow model.Used with permission of the publisher, Manning Publications, Co. Please see Resources for more book information.

Date:  01 Jan 2002
Level:  Introductory

Activity:  9134 views
Comments:  

[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: 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.

The WSFL flow model

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: 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>



Selecting service providers

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 bindTime attribute 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.
    The selectionPolicy defines 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.

Aggregating operations

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"/>



To be continued

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.


Resources

About the author

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.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and Web services
ArticleID=11638
ArticleTitle=WSFL in action, Part 1
publish-date=01012002
author1-email=awesley@us.ibm.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers