Partilhar via


Implementing Service-Oriented Integration with BizTalk Server 2004

 

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

patterns & practices Developer Center

Integration Patterns

Contents

Context

Background

Implementation Strategy

Example

Resulting Context

Testing Considerations

Security Considerations

Operational Considerations

Acknowledgments

Context

You are connecting two or more systems by using Service-Oriented Integration. The service implementation requires the orchestration of multiple functions.

Background

In the Global Bank scenario, the customer can view his or her balances for all accounts, including loan accounts, on a single page. To provide this function, the Web application server interacts with multiple systems to retrieve the required information. The loan accounts may reside on multiple external loan systems that are operated by subsidiaries that were acquired over time. Figure 1 shows how the Web application server interacts with the multiple systems to display the account information in the customer's Web browser.

Ff649948.implsoiwithbts_f01(en-us,PandP.10).gif

Figure 1. Aggregated account balances from multiple banks

To hide the complexity of interacting with external loan systems, you want to design a service that the Web application server can easily access by using a single GetOtherLoans request.

Implementation Strategy

This pattern implements a Microsoft BizTalk Server 2004 orchestration and exposes it as a Web service. Before discussing detailed steps, it is helpful to review the concept of Service-Oriented Integration and to review some details about BizTalk Server orchestrations.

Service-Oriented Integration

Service-Oriented Integration connects applications by exchanging documents. In many cases, these documents are represented in XML format. The following code shows a document passed in a SOAP envelope.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope>
  <soap:Body>
    <LoanBalanceRequest>
      <MasterCustomerID>12345678</MasterCustomerID>
      <CorrelationID>1100222</CorrelationID>
    </LoanBalanceRequest>
  </soap:Body>
</soap:Envelope>
  

Service-Oriented Integration hides the complexity of the underlying service very well. For example, the service might execute a complex process internally that has many parallel threads of activity. However, the complex internal process does not affect the service interface at all (see Figure 2).

Ff649948.implsoiwithbts_f02(en-us,PandP.10).gif

Figure 2. Complexity hidden behind a service-oriented interface

Exposing a BizTalk Orchestration as a Web Service

You can use BizTalk Server 2004 to model complex processes by using the BizTalk Orchestration Designer. BizTalk orchestrations interact with the outside world through logical ports as shown in Figure 3. An orchestration can interact with logical ports through send and receive ports that are incorporated into the orchestration graph. Messages received from a receive port can start a new instance of an orchestration or interact with an existing orchestration instance. An orchestration can send messages to any output port through the send port. A sent message can either be the response to a previously received message or to a standalone message.

Ff649948.implsoiwithbts_f03(en-us,PandP.10).gif

Figure 3. An orchestration invoked by a Web service call

Logical ports can be bound to physical ports at design time or at deployment time. Physical ports specify a transport type, such as File, File Transfer Protocol (FTP), HTTP, or SOAP. Physical ports also specify a physical location, such as a directory name or a URL. This separation of logical and physical ports allows you to create and reuse orchestrations without being tied to specific directory names or URLs. You can specify a physical Web port by selecting the SOAP transport protocol and by specifying a URL.

After you design an orchestration in BizTalk Server, you can expose it as a Web service to be invoked from other applications. The BizTalk Web Services Publishing Wizard supports this task, generating both a physical port definition and an ASP.NET Web service that invokes the orchestration when it receives a SOAP request. For a more detailed description of ASP.NET Web services, see Implementing Service-Oriented Integration with ASP.NET.

The following steps are necessary to create a BizTalk orchestration and to expose it as a Web service to be consumed by other applications. To illustrate this procedure, all steps here are performed manually. However, you can automate some steps by scripting to the BizTalk Windows Management Instrumentation (WMI) interface.

To expose a BizTalk orchestration as a Web service

  1. Define the message schemas for inbound and outbound messages. The message schemas define the format of the messages that the orchestration receives and sends. Ultimately, the Web Services Description Language (WSDL) document generated by the ASP.NET Web service uses these message schemas to specify the required format for inbound and outbound SOAP messages.
  2. Define logical request-response ports. A logical port is required so that the orchestration can receive and send messages. A request-response port is a port that receives a request message and that sends a response within the same interaction.
  3. Define the orchestration and connect it to the logical port. The orchestration encapsulates the tasks that the service needs to execute internally. Connecting to the logical port starts a new instance of the orchestration every time a new message arrives on the port.
  4. Build and deploy the orchestration. An orchestration has to be built and deployed to the global assembly cache and to the BizTalk Management database before it can be executed. You use the BizTalk Deployment Wizard to deploy the orchestration.
  5. Run the BizTalk Web Services Publishing Wizard. The wizard creates and compiles a Microsoft Visual Studio project for an ASP.NET Web service. If you select the Create BizTalk Receive Location option, the wizard also creates a physical port definition in the BizTalk configuration database.
  6. Bind the orchestration's logical port to the physical port. Before you can start the orchestration, you must bind the logical port definition referenced by the orchestration to a physical port. To do this, you usually use BizTalk Explorer from within Microsoft Visual Studio .NET. In this case, you bind the logical port to the physical port that the Web Services Publishing Wizard created.
  7. Start the orchestration. When you start the orchestration, it begins to actively listen to incoming messages. In this case, the incoming messages are SOAP requests. The service is now live and executes the orchestration for each incoming SOAP request.
  8. Create a test client that invokes the Web service. The ASP.NET Web service generated by the Web Services Publishing Wizard renders the necessary WSDL document that describes the public service contract. This means that you can use the Web Services Description Language tool (Wsdl.exe) or Visual Studio .NET to easily create applications that consume the newly created Web service.

Example

The following example explains the architectural decisions involved and the steps performed in building the Global Bank solution.

Asynchronous Interaction

In the Global Bank scenario, customers can view their account balances, including loan balances, on a single page. The loan balances, however, must be retrieved from external systems that may not always be available or that may have slow response times. Users indicated that quick response times for the Web site were more important than complete information. Therefore, given that the system cannot guarantee quick response times, the user requirements state that loan balances are optional for display on the View Scheduled Payments page.

This optional user requirement is reflected in the solution architecture by making the request for the loan balances asynchronous. This means that the Web application server requests the loan balances first, and then it retrieves data from the mainframe and payment systems. After all other data has been retrieved, the application server checks whether the loan balances were retrieved. If so, they are incorporated into the page display. If not, the page is rendered without the loan balance portion. Figure 4 shows the concurrent action in Unified Modeling Language (UML). The interaction between BizTalk Server and the individual loan systems is not shown.

Ff649948.implsoiwithbts_f04(en-us,PandP.10).gif

Figure 4. Asynchronous interaction between the Web application server and BizTalk Server

Implementing Asynchronous Web Services

To make the interaction between the Web application server and BizTalk Server asynchronous, you have three implementation choices. The three implementation choices are illustrated in Figure 5.

Ff649948.implsoiwithbts_f05(en-us,PandP.10).gif

Figure 5. Implementation choices for asynchrony between the Web application server and BizTalk Server

The three implementation choices from Figure 5 can be summarized as follows:

  1. Client-side asynchrony. The Web server issues a single SOAP request by using the asynchronous Web service API. This API permits the client (in this case, the client is the Web application server) to continue with other processing and to read the results of the request at a later time. This approach permits the client to operate asynchronously while the interaction with BizTalk Server is synchronous.
  2. Asynchronous interaction with polling. The Web server makes two SOAP requests to BizTalk Server. One of the SOAP requests initiates the request for loan information. This first request only initiates processing on the BizTalk Server side and returns immediately. Subsequently, the Web server issues a second SOAP request to poll for the results. BizTalk Server returns the results if they are available or returns a blank message if they are not yet available. BizTalk Server discards the loan balance results if they become available after the Web server polled for them.
  3. Asynchronous interaction with callback. The Web server issues a single SOAP request to initiate the retrieval of loan information. As with option B, control is returned immediately to the Web server. The Web server then goes on to other work. After BizTalk Server has retrieved the loan information, it sends a SOAP request back to the Web server to pass the loan information. It is important to note that for this part of the interaction, the Web server has to be able to service incoming SOAP messages. Therefore, the Web server has to act as the server. The Web server stores the loan information in a global cache that is accessible to the threads that generated the requests. Before the Web server renders the HTML page, it checks the global cache to see whether any loan information has arrived while it was interacting with the mainframe and the Customer Relationship Management (CRM) systems.

To choose the best option, you need to evaluate the advantages and disadvantages of each option. Table 1 compares the different options.

Table 1: Comparison of the Implementation Choices for Asynchronous Interaction

  Option A: client-side asynchrony Option B: asynchronous interaction with polling Option C: asynchronous interaction with callback
Client-side implementation effort Low Medium High
Server-side implementation effort Low Medium Medium/low
Network traffic Low Higher Higher
Efficient use of resources Poor (for long-running interactions) Good Good
Where state is kept Connection Server Client

As you can see, each option has its advantages and disadvantages. Therefore, you must make your decision based on the priorities that you assign to the individual criteria.

Although option A may be the easiest to construct, it is essentially a synchronous SOAP interaction that just appears to be asynchronous to the client code because the connection between the client and the service remains active throughout the whole interaction. The use of long-standing connections can quickly deplete system resources and can be one of the biggest impediments to a solution's scalability. Because the loan balance service has to access external loan systems over slow and unreliable connections, the interaction can definitely be long running. Therefore, you should eliminate option A.

The choice between option B and C is more difficult and depends on whether you want to maintain the state on the client (the Web application server) or on the server running BizTalk Server. Both servers are multithreaded and quite efficient at keeping state for many concurrent requests. The choice also depends on where you want to allocate the additional development effort. Do you prefer to put additional effort into the ASP.NET code on the Web server or into the orchestration design on the server running BizTalk Server? Option B requires a little extra work on the BizTalk Server to ensure proper correlation and to allow the concurrent servicing of multiple requests. Option C requires additional coding effort in the Web server to maintain and to clear the global cache. Overall, option B offers the best results for the smallest amount of development effort and is the first choice. However, this discussion highlights that architectural decisions are not only based on technical considerations alone but also on development resource constraints and skills preferences.

Building the Solution

Based on the tradeoffs discussed in the previous section, Global Bank decided to use option B, asynchronous interaction with polling. The next step was to start building the solution. The rest of this example shows you the steps required to build the Global Bank solution. Due to the large number of steps involved in creating the solution, some steps are not covered in full detail.

Step 1: Define the Message Schemas for Inbound and Outbound Messages

To define the format of the request and response messages, create two XML Schema (XSD) files in the Visual Studio .NET XSD Editor. The XSD schema for the LoanBalanceRequest.xsd request message looks like the following schema. To improve readability, the namespace declarations are omitted.

<xs:schema>
  <xs:element name="LoanBalanceRequest">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="1" name="MasterCustomerID"
                    type="xs:string" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
  

The document specifies a single MasterCustomerID data field for the request message. The MasterCustomerID field is common across all systems and can be used to locate all the customer's accounts.

In response to the request, the application returns the following acknowledgement (Ack.xsd).

<xs:schema>
  <xs:element name="Ack">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="CorrelationID" type="xs:string" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
  

The only field in this schema is a unique correlation identifier. The orchestration assigns an ID to this field and uses it later to match (or correlate) the request and response messages across the asynchronous communication. For more information, see the Correlation Identifier pattern in Enterprise Integration Patterns [Hohpe04].

After receiving the acknowledgment response from the orchestration, the client polls the orchestration for the result.

The client application copies the correlation identifier returned in the acknowledgment message (Ack.xsd) into PollReq.xsd. PollReq.xsd has only one field (CorrelationID), as shown in the following schema.

<xs:schema>
  <xs:element name="PollReq">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="CorrelationID" type="xs:string" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
  

The XSD code for the LoanBalanceResponse.xsd response message looks like the following.

<xs:schema >
  <xs:element name="LoanBalanceResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Loan">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Name" type="xs:string" />
              <xs:element name="AccountID" type="xs:string" />
              <xs:element name="Amount" type="xs:decimal" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
  

The response message schema defines a list of account names and balances. This list is filled in by the Web service (through the orchestration). The completed message is then sent back to the client.

Step 2: Define Logical Request-Response Ports

In BizTalk Orchestration Designer, add a port to the orchestration, and then use the Port Configuration Wizard to configure a public request-response port. Figure 6 indicates the Request-Response option.

Ff649948.implsoiwithbts_f06(en-us,PandP.10).gif

Figure 6. Using the BizTalk Port Configuration Wizard to add a request-response port

In addition to selecting the Request-Response setting, you must change the Access Restrictions setting to Publicno limit.

Step 3: Define the Orchestration and Connect It to the Logical Port

As described in "Implementing Asynchronous Web Services," the interaction between the Web server and the BizTalk Server orchestration consists of two parts:

  • The Web server requests loan information from BizTalk Server.
  • The Web server polls for results. The BizTalk Server orchestration returns a response immediately with the results it retrieved up to that point.

Based on Global Bank requirements, the orchestration must:

  1. Receive the initial request from the Web server. The orchestration creates a new instance of the orchestration for each request.
  2. Generate a unique correlation identifier to pass back to the client. The orchestration returns the correlation identifier back to the Web server so that it can use this identifier to poll later for the results.
  3. Request the loan balance from multiple backend loan systems. These requests can be made concurrently. The results from each loan system have to be combined into a single message. In this example, both loan systems are accessible through prebuilt Web services.
  4. Service the polling request. The orchestration has to be able to receive a polling request from the Web server at any time. When it receives a polling request, the orchestration returns the loan balances if they have been obtained already. Otherwise, the orchestration returns a blank result. The polling request can arrive at any time after the initial request.
  5. Time out. If the orchestration does not receive a polling request after an extended period of time (for example, 60 seconds), the orchestration is terminated. This function keeps orchestration instances from staying active indefinitely while they are waiting for a polling request.

Figure 7 shows these tasks modeled inside a BizTalk Server orchestration.

Click here for larger image

Figure 7. The BizTalk Server orchestration for loan balances (Click the image to enlarge it)

Now, let's examine the orchestration tasks in more detail. The letters in the following list correlate to the letters in Figure 7.

A: Receive the Initial Request from the Web Server

In the Global Bank scenario, the ASP.NET client sends a request for a customer's loan balances (GetOtherLoans) to BizTalk Server. LoanBalanceRequest.xsd defines the format of the request. The request contains only the MasterCustomerID field (see "Step 1: Define the Message Schemas for Inbound and Outbound Messages").

The request is received through the ReceiveReq port in the orchestration (see Figure 7). After the message is received, the port forwards it to the ReceiveReq Receive shape. The Activate property of the ReceiveReq Receive shape is set to True, which activates the orchestration.

B: Generate a Correlation Identifier and Send Acknowledgment

After the ASP.NET client sends the initial request to BizTalk Server, it receives an acknowledgment message (Ack.xsd). This message contains the CorrelationID field. The CorrelationID field identifies the orchestration instance associated with the initial request. This field guarantees that incoming messages are associated with the correct instance of the orchestration.

To create the correlation ID, you can use a custom C# class that uses System.Random to generate and return an ID. That ID is assigned to the CorrelationID field of the Ack.xsd message, and it is returned to the client. Alternatively, you can assign one of the BizTalk Server message context properties (BTS.MessageID) as a unique ID to the CorrelationID field of the Ack.xsd message. This is accessible within an Expression shape in the orchestration.

For the CorrelationID field to be accessible to the code in the Expression Editor window, you must use the BizTalk Schema Editor to promote it, as shown in Figure 8.

Ff649948.implsoiwithbts_f08(en-us,PandP.10).gif

Figure 8. Promoting a schema field

After the acknowledgment response is created, the Send_Ack send shape sends the response to the receive-request port, and the receive-request port then returns it to the client. The Send shape should be configured to initialize the orchestration correlation set. To accomplish this, add a correlation type and a correlation set in the Orchestration Viewer, and then set the Initialize Correlation property of the Send shape to the new correlation type you created. When the orchestration sends the message to the client, the correlation set is automatically initialized with the value in the CorrelationID field.

C: Request the Loan Balances

The initial request from the client activated the orchestration. The orchestration then synchronously returned an acknowledgment containing the CorrelationID to the client. Now, to retrieve the customer's loan balance, the orchestration needs to call the external systems that are implemented as two Web services, GetOtherLoans1.asmx and GetOtherLoans2.asmx. The request and response messages to these Web services are fairly simple. Each takes a customer ID as a request and returns the loan information that corresponds to that customer ID. This is shown in the following selection from the GetOtherLoan1.asmx external Web service request schema.

<?xml version="1.0" encoding="utf-16" ? > 
  
<xs:schema ..>
<xs:element name="Request">
<xs:complexType>
<xs:sequence>
 <xs:element name="CustomerId" type="xs:string" /> 
 </xs:sequence>
 </xs:complexType>
 </xs:element>
 </xs:schema>
  

Note   The namespace information in these examples is omitted here for brevity.

At this stage, the client's request must be transformed into the message format that the external Web services require. Each external Web service can have a different schema, although both schemas are identical in this example. The following is the key portion of the GetOtherLoans1.asmx external Web service response schema.

<?xml version="1.0" encoding="utf-16" ? > 
  
    <xs:schema >
        <xs:element name="Response">
<xs:complexType>
        <xs:sequence>
<xs:element name="Name" type="xs:string" /> 
<xs:element name="Amount" type="xs:string" /> 
<xs:element name="AccountNo" type="xs:string" /> 
        </xs:sequence>
                 </xs:complexType>
      </xs:element>
     </xs:schema>
   

To transform one schema into another, Transform shapes in ConstructWS_Req1 and ConstructWS_Req2 map the CustomerId fields of the two schemas. You use the BizTalk Mapper to map the MasterCustomerID field of LoanBalanceRequst.xsd to the CustomerId field of the Web service's request schema (see Figure 9).

Click here for larger image

Figure 9. Using BizTalk Mapper to map request fields (Click the image to enlarge it)

Now that the Web services' request messages have been constructed, the response messages have to be parsed and consumed. In BizTalk Solution Explorer, open the Web service's Reference.xsd file. Using the Promote option, distinguish the Name, AccountNo, and Amount elements of the Web service response schema (see Figure 8). Distinguishing these fields allows the code in the AddLoan1 and AddLoan2Expression shapes to reference their values and use them to construct the response document.

Next, you use the response from each Web service to construct a LoanBalanceResponse.xsd response that is returned to the client. To accomplish this, AddLoan1 and AddLoan2Expression shapes use a custom C# class (LoanInfoCollection) to collect the results returned by each Web service. Each Web service returns the Name, AccountNo, and Amount for the customer's loan. The custom class aggregates the responses into an XML document which is returned to the polling client as the LoanBalanceResponse.xsd response. The following is the code from the Expression property of AddLoan1.

LoanInfoCollection.AddLoan(
msgWebServ1_Resp.GetLoanInfoResult.Name,
msgWebServ1_Resp.GetLoanInfoResult.Amount,
msgWebServ1_Resp.GetLoanInfoResult.AccountNo);
  

Because all three branches of the parallel action use the LoanInfoCollection class, the AddLoan1 and AddLoan2Expression shapes are inside synchronized blocks (Scope_LoanInfo1 and Scope_LoanInfo2 respectively). The Transaction Type property of the synchronized blocks is set to Atomic to protect the class from concurrent access. For more information about transactions in BizTalk Server, see Implementing Process Integration with BizTalk Server 2004.

D: Service Polling Request

At this point, the response message has been constructed and is ready to be delivered to the client. The client polls the orchestration by sending a SOAP message to BizTalk Server. The message contains the correlation ID that identifies the instance of the orchestration that is associated with this request.

The PollReqResp port is linked to the ReceivePollReq receive shape. The ReceivePollReq receive shape has an important property, Following Correlation Sets. This property is set to the correlation type created earlier in step B, and it allows BizTalk Server to associate the polling request to the correct instance of this orchestration.

The request message is then assigned the loan information gathered from Web services by the LoanInfoCollection class within the Construct Response shape of Scope_CreateResponse.

As the final step, the SendPollResp Send shape sends the constructed response message that is mentioned earlier to the PollReqResp port. The PollReqResp port then sends the constructed response message to the polling client.

E: Time Out

With respect to the polling request, there are two potential scenarios that you have to design the orchestration to handle properly. In the first scenario, the client may poll too early, before the orchestration has received a response from external Web services and constructed the response message. In the second scenario, the client may not poll at all. If the client does not poll at all, the orchestration instance is left in an active state forever.

To handle early polling, you must allow the client to poll again if no results are returned. To accomplish this, you add a loop and set it to run indefinitely. In this case, add a Poll_Loop. Note, however, that the loop is limited by the Timeout property value of the orchestration.

To set the Timeout value for the orchestration, set the Transaction Type property to Long Running, and set the Timeout property value to 60 seconds or another appropriate value. This allows the client enough time to poll for the result and eliminates the possibility that an orchestration could run indefinitely.

Step 4: Build and Deploy the Orchestration

Before you build the orchestration, create an assembly key file by typing snk SOIwithBizTalk.snk at the command prompt. Copy the file to the project folder, and then enter the file name in the Assembly Key File name property of the project properties.

Note   You need to build the LoanInfoCollection assembly that is referenced by the project by using a strong name assembly key file. You then must deploy it to the global assembly cache.

From the Visual Studio .NET menu, build the solution. This creates a .NET Framework assembly called SOIwithBizTalk. You then deploy the SOIwithBizTalk assembly by using the BizTalk Server Deployment Wizard or by using the scripts that are included with the BizTalk 2004 SDK.

Step 5: Run the BizTalk Web Services Publishing Wizard

To expose the SOIwithBizTalk assembly that you deployed in step 5 as a Web service, run the BizTalk Web Services Publishing Wizard. The wizard creates the SOIwithBiztalk_Proxy Web service. The SOIwithBiztalk_Proxy Web service exposes Web services corresponding to the ReceiveReq and PollReqResp ports.

Step 6: Bind the Orchestration's Logical Port to the Physical Port

The Web Services Publishing Wizard that you ran in step 4 also created two receive ports for the ReceiveReq and PollReqResp ports, which you can access through BizTalk Explorer.

Note   The Receive Pipeline property of these ports should be set to XmlReceive. To set this property in BizTalk Explorer, select the port, right-click the port name, and then click Edit on the context menu.

Next, you need to add two send ports for the GetOtherLoan1 and GetOtherLoan2 Web ports. The Receive Pipeline properties of these ports also should be set to XmlReceive instead of the default PassThrough setting.

After you set up the physical ports, bind the orchestration to these ports in BizTalk Explorer. Note that there are two inbound ports and two outbound ports in the Port Binding Properties window of the orchestration. You can also use the BTSDeploy command line utility and a binding file to bind ports. Use the Export BizTalk assembly binding to file option in BizTalk Deployment Wizard to create the binding file.

Step 7: Start the Orchestration

After binding the logical ports to physical ports, start the orchestration in BizTalk Explorer.

Step 8: Create a Test Client That Invokes the Web Service

To test the orchestration, you need to create a client that consumes the Web service created from the orchestration in step 4. As you saw in step 4, the wizard created two Web services that correspond to the two request-response ports of the orchestration. The following code shows part of the WSDL file for PollReqResp.asmx. For the sake of clarity, some parts of the file are not shown here.

  <types>
   + <s:schema elementFormDefault="qualified" targetNamespace="https://msdn.microsoft.com/soi">
   - <s:schema elementFormDefault="qualified" targetNamespace="http://SOIwithBiztalk.PollReq">
       <s:element name="PollReq" type="s1:PollReq" />
      - <s:complexType name="PollReq">
         <s:sequence>
          <s:element minOccurs="0" maxOccurs="1" form="unqualified" name="CorrelationId" type="s:string" />
        </s:sequence>
      </s:complexType>
    </s:schema>
  - <s:schema elementFormDefault="qualified" targetNamespace="http://SOIwithBiztalk.PollResp">
      <s:element name="PollResp" type="s2:PollResp" />
    - <s:complexType name="PollResp">
     -  <s:sequence>
          <s:element minOccurs="0" maxOccurs="1" form="unqualified" name="Loans" type="s2:ArrayOfPollRespLoan" />
        </s:sequence>
      </s:complexType>
   -  <s:complexType name="ArrayOfPollRespLoan">
     -  <s:sequence>
          <s:element minOccurs="0" maxOccurs="unbounded" form="unqualified" name="Loan" type="s2:PollRespLoan" />
        </s:sequence>
      </s:complexType>
    - <s:complexType name="PollRespLoan">
     -  <s:sequence>
          <s:element minOccurs="0" maxOccurs="1" form="unqualified" name="Amount" type="s:string" />
          <s:element minOccurs="0" maxOccurs="1" form="unqualified" name="Name" type="s:string" />
          <s:element minOccurs="0" maxOccurs="1" form="unqualified" name="AccountNo" type="s:string" />
        </s:sequence>
      </s:complexType>
    </s:schema>
  </types>
+ <message name="PollReqRespSoapIn">
+ <message name="PollReqRespSoapOut">
+ <portType name="SOIwithBiztalk_SOIwithBiztalk_Orchestration_PollReqRespSoap">
+ <binding name="SOIwithBiztalk_SOIwithBiztalk_Orchestration_PollReqRespSoap" type="s0:SOIwithBiztalk_SOIwithBiztalk_Orchestration_PollReqRespSoap">
- <service name="SOIwithBiztalk_SOIwithBiztalk_Orchestration_PollReqResp">
    <documentation>BizTalk assembly "SOIwithBiztalk, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c6495a1a84cf8ad3" published web service.</documentation>
  - <port name="SOIwithBiztalk_SOIwithBiztalk_Orchestration_PollReqRespSoap" binding="s0:SOIwithBiztalk_SOIwithBiztalk_Orchestration_PollReqRespSoap">
      <soap:address location="https://localhost/SOIwithBiztalk_Proxy/SOIwithBiztalk_SOIwithBiztalk_Orchestration_PollReqResp.asmx" />
    </port>
  </service>
</definitions>

The test client is a Windows Form application that uses the NUnit test tool. For more information about this tool, see www.nunit.org. The following test case sends a request to BizTalk Server, waits, and then polls for the result.

 [Test]
   public void TestRequestAndPollLater()
   {
         RequestWS.SOIwithBiztalk_SOIwithBiztalk_Orchestration_ReceiveReq ws = new TestSOIwithBiztalk.RequestWS.SOIwithBiztalk_SOIwithBiztalk_Orchestration_ReceiveReq();
   RequestWS.Request req = new RequestWS.Request();
   req.MasterCustomerID = "1234";
   RequestWS.Ack resp = ws.InitialRequest(req);
         
   string corId = resp.CorrelationId;
   //wait for external services to return response
   System.Threading.Thread.Sleep(6000);
   //poll for result         PollWS.SOIwithBiztalk_SOIwithBiztalk_Orchestration_PollReqResp pollws = new TestSOIwithBiztalk.PollWS.SOIwithBiztalk_SOIwithBiztalk_Orchestration_PollReqResp();
   PollWS.PollReq pollreq = new TestSOIwithBiztalk.PollWS.PollReq();
   pollreq.CorrelationId = corId;

   PollWS.PollResp pollresp = pollws.PollReqResp(pollreq);

   Assertion.AssertEquals(2, pollresp.Loans.Length);
   //test results
   ValidateLoanEntry(pollresp.Loans[0]);
   ValidateLoanEntry(pollresp.Loans[1]);
}

   private void ValidateLoanEntry(PollWS.PollRespLoan entry)
   {
      // note: the responses do not have to be in order
      if (entry.AccountNo.Equals("1234")) 
      {
         Assertion.AssertEquals("1000", entry.Amount);
      }
      else if (entry.AccountNo.Equals("5678")) 
      {
         Assertion.AssertEquals("2000", entry.Amount);
      }
      else 
      {
         Assertion.Fail("Wrong account number");
      }
    }
  

Resulting Context

This implementation of Service-Oriented Integration results in the following benefits and liabilities:

Benefits

  • Powerful. You can use BizTalk Server 2004 to model complex processes comprising multiple parallel interactions. You can even build a hierarchy of orchestrations where one orchestration invokes other orchestrations. BizTalk Server also imports important concepts that are critical when developing asynchronous, event-driven solutions. These solutions include correlation, synchronization, timeouts, long-running transactions, and compensating actions.
  • Integrated development tools. The BizTalk Server 2004 visual modeling tools are integrated into Visual Studio .NET. This greatly enhances the development experience for mixed development consisting of actual C# or Visual Basic .NET code and visual models from maps and orchestrations.
  • Operational support. Monitoring and operating Web services solutions can be difficult. BizTalk Server 2004 includes sophisticated tools to monitor the flow of messages and the execution of orchestrations through the Health and Activity Tracker (HAT) tool.

Liabilities

  • Complexity. Although BizTalk Server 2004 provides many useful features, it also introduces a series of new concepts, a large number of moving parts, and a different development environment than what developers are used to. This can increase the learning curve for application developers.

Testing Considerations

There are several possible options available when testing this implementation. First, the Web service as a whole can be tested by writing a test client in the .NET Framework. To create the test client, create a new C# console application, and use the Add Web Reference command in Visual Studio Solution Explorer to create a reference to the orchestration Web service. You can then write test code that invokes the Web service. Subsequently, you can add automated test cases to this test client by using test tools such as NUnit.

After running the test client, you can use the Orchestration Debugger to examine traces of the orchestration execution. You can access the Orchestration Debugger from the HAT tool and use the Orchestration Debugger in two modes: reporting mode and interactive mode. Reporting mode tracks the execution of each shape in the orchestration as it occurs. In reporting mode, you can replay the steps or set breakpoints on the class of orchestration so that you can then debug new instances in interactive mode. Interactive mode enables you to debug a currently running instance. To debug a process interactively, set a breakpoint within an orchestration while in reporting mode, and then submit a new message (create a new instance of an orchestration). The orchestration will stop at the breakpoint, and you can then attach the orchestration debugger to that instance.

Security Considerations

The Web service implementation presented here does not address security considerations. Appropriate security measures are essential in this scenario because the Web service exposes sensitive account data that resides in the bank's mainframe computer. Even though the Web service resides behind the firewall, you would not want unauthorized users to create a client to this service to retrieve customers' account balances.

Security is implemented at multiple levels when exposing an orchestration as a Web Service:

  • Transport security. The BizTalk Web Services Publishing Wizard creates an ASP.NET virtual directory like any other ASP.NET Web service. SOAP messages sent to this virtual directory can be sent by using HTTPS (encrypted). Additionally, the virtual directory can be configured to require basic authentication, NTLM authentication, or even client certificates.
  • SOAP security. Microsoft has partnered with IBM and VeriSign to develop the Web Services Security (WS-Security) specification. The WS-Security specification describes how SOAP messages can be augmented with security certificates. The WS-Security specification is currently implemented by Web Services Enhancements (WSE) for Microsoft .NET. The current version of the SOAP adapter does not support WS-Security, but this functionality can be supported by using custom pipeline components in the BizTalk receive and send pipelines.
  • Receive adapter security. The SOAP adapter is run by a BizTalk Server Isolated Host instance within a specific Microsoft Windows security context. If the BizTalk Isolated Host was installed as trusted, then the user that acquires authentication when running the Web service must be a member of the BizTalk Isolated Host Users group (this is often the IUSR_computer name account). If the BizTalk Isolated Host was not installed as trusted, the ASP.NET account must be a member of the BizTalk Isolated Host Users group.
  • Receive port security. You can configure the receive port to require messages to be authenticated before they are processed. Messages are authenticated in the ResolveParty stage of the receive pipeline by using a client certificate or by using a Security Identifier (SID). Messages that are not authenticated can either be dropped or saved, but they are not processed.

Operational Considerations

Many of the BizTalk receive adapters, including the HTTP and the SOAP adapters, perform batching to optimize throughput and server resource utilization by minimizing polling. The default batch size is 10, and there is a delay between polls of one second. This means that a single synchronous HTTP post or SOAP call is processed, but because it is not a complete batch, the adapter waits for one second before polling again. Therefore, successive calls may be delayed. This is appropriate behavior in high-transaction situations, but it is not appropriate behavior for a highly responsive system.

To make the HTTP and SOAP adapters more responsive, you can set the registry HttpBatchSize subkey DWORD value in the HKLM\CurrentControlSet\BtsSvc 3.0\HttpReceive registry key to 1. Setting this value to 1 affects the maximum throughput that the adapter is capable of handling.

Acknowledgments

[Hohpe04] Hohpe, Gregor, and Bobby Woolf, Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions. Addison-Wesley, 2004.

Start | Previous | Next

patterns & practices Developer Center

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

© Microsoft Corporation. All rights reserved.