Implementation Notes

These are the major items that must be completed for this project:

1.
Design and implement the order database.

2.
Develop the OrderHandler WSC component.

3.
Install and configure the Microsoft SOAP Toolkit.

4.
Create the required support files to expose the OrderHandler object as a SOAP service.

5.
Round-trip test the entire system using a SOAP client.

The tools that will be required to complete these steps include the following:

  • A text editor (or XML editor)

  • The Microsoft SOAP Toolkit

  • Microsoft Access (or another tool capable of designing an Access database)

Before anything else can be done, the database that will capture orders must be designed.

Designing the Order Database

In a real-world situation, there would most likely be some type of order-processing system already in use, and this step would not be required. However, the techniques for interfacing with a simple Access database do not differ greatly from those for accessing a larger production database. Figure 15.2 shows an Entity Relationship Diagram (ERD) for the database that can be found in OrderDatabase.mdb.

Figure 15.2. An entity relationship diagram for OrderDatabase.mdb.


Note

The cryptic abbreviations in the ERD in Figure 15.2 refer to the various database roles that a particular column plays:

  • PK—Primary Key

  • FK—Foreign Key

  • I—Index


The structure is very simple. Each order will occupy a single row in the Orders table. The list of items and quantities associated with a particular order will be inserted into the Items table, using the order ID (idOrder) to relate them back to an order record.

Writing the OrderHandler Component

Before tackling the implementation of the OrderHandler object, a quick introduction to Windows Scripting Components is in order.

Most Web developers working in a Microsoft environment have had some contact with the Microsoft Scripting Runtime, most likely from developing Active Server Page (ASP) applications. In an ASP application, script fragments are embedded within static content (such as HTML). These script fragments can then deliver dynamically generated content to the Web browser client. ASP scripts can also create and reference COM objects, allowing for almost unlimited extensibility.

WSC Development

The WSC framework is a feature of the Microsoft Scripting Runtime that allows COM objects to be developed using the same scripting engine that drives ASP pages. The structure of the COM object (registration information, methods, properties, events, and so on) is encoded in a simple XML format. The resulting XML document may then be registered using the standard COM object registration procedure (regsvr32.exe).

WSC files may be created using nothing more than a text or XML editor. Also, if you download the Microsoft Windows Script toolkit, you also get the Script Component Wizard. This tool automates the process of creating a WSC file, creating a GUID, and so forth. For more information about the Microsoft Windows Script toolkit, see the Web site.

Listing 15.1 shows the bare XML skeleton of the OrderHandler object, before the actual code has been written. The entire working component is available on the Web site as OrderHandler.wsc.

Listing 15.1. The XML skeleton of the OrderHandler component.
<?xml version="1.0"?>
<package>
  <?component error="true" debug="true"?>

  <component>

    <registration
        description="Order Handler Object"
        progid="SXML.OrderHandler"
        version="1.00"
        classid="{ ad1afddc-73c8-468e-9700-371eff4a1156}">
    </registration>

    <reference object="ADODB.Recordset"/>

    <public>
        <method name="ProcessOrder">
            <parameter name="strCustomerName"/>
            <parameter name="strCCNum"/>
            <parameter name="strEmailName"/>
            <parameter name="strEmailDate"/>
            <parameter name="astrPartNums"/>
            <parameter name="astrQuantities"/>
        </method>
    </public>

    <implements type="ASP" id="ASP"/>

    <script language="VBScript">
    <![CDATA[
Option Explicit

' !!!LATER!!! object implementation goes here
    ]]>
    </script>

  </component>
</package>
						

WSC Document Structure

The following sections discuss the components of a WSC file in more detail.

<package> Element

In this example, the top-level <package> element is technically unnecessary. If only one COM object is being declared (only one <component> element is present), the <component> element itself may be the top-level element. If more than one component will be declared in a single document, they all must be contained by a top-level <package> element. On the other hand, it costs nothing to include the <package> element, and it will simplify life if we choose to declare additional components in the future.

<component> Element

This element is the one used to actually declare a COM object that can be instantiated by other programs. Everything related to that object will be contained in an element within the top-level <component> element. Multiple <component> elements may be included in a single top-level <package> element, simplifying deployment of complex COM framework packages. All declared components are registered or unregistered simultaneously whenever the WSC file is passed to regsvr32.exe.

<?component?> Processing Instruction

The <?component?> processing instruction is used to tell the scripting runtime how to handle runtime errors and debugging requests. In this case, both the error and debug attributes are set to true, indicating that runtime errors should be reported, and the script debugger should be invoked to debug errors as they occur. Debugging WSC components is somewhat of a black art, because errors can occur due to malformed XML, syntax errors in the underlying scripting code, mismatches between the object property and method declarations, or runtime programming errors.

Debugging works differently depending on whether the object was created by an interactive process (such as a .vbs script file) or in a background context (such as from an ASP page). It is generally preferable to do any debugging and troubleshooting using an interactive test script before attempting to deploy the object using IIS. See the Web site for a short description of the problems with debugging Windows Scripting Components in a non-interactive environment.

<registration> Element

This element contains all the information that will be used to register the COM object in the Windows registry. The element supports several attributes that control how the object is instantiated and used:

  • description— A human-readable description of the component. Some development tools will make this string available to the programmer. This attribute is optional.

  • progid— A friendly name (instead of the somewhat less-than-friendly class ID) that can be used to instantiate this COM object using a call such as Server.CreateObject(). This attribute is optional, if a classid attribute is present.

  • version— A version number for this component. Although this attribute is optional, it is a good idea to set it and update it regularly as your object evolves. It simplifies debugging if you know which version of your object is actually being created.

  • classid— This attribute may contain a Globally Unique Identifier (GUID) that positively identifies your component as distinct from any other component. If you created the component with the Microsoft Script Component Wizard, your object was automatically assigned a GUID. Another way to generate a GUID is by using the Microsoft UUIDGEN.EXE tool (shipped with most MS development tools).

There are additional attributes and features of the <registration> tag, which you can find in the documentation that ships with the Microsoft Windows Script toolkit.

<reference> Element

This element imports the type information from a COM type library. This allows your script code to use symbolic constants when calling methods of COM objects associated with the imported type library. In this case, the component is importing the type information associated with the Microsoft ADO Recordset object.

<public> Element

This element is used to expose the component's public properties, methods, and events. The OrderHandler object has only one method, the ProcessOrder()method. The method is exposed using the <method> element, which contains multiple <parameter> elements that expose the arguments to the method.

After a method has been exposed using the <method> element, a corresponding script sub routine or function must be written in a <script> block within the <component> element. Exposing a method without providing an implementation will cause the scripting library to generate a runtime error, even if that method is never called by client code.

Besides the <method> element, the <public> element may also contain <property> and <event> elements.

<implements> Element

This specialized element indicates that your component will support one of the nonstandard COM interfaces predefined by the WSC framework. In this case, the component is marked as supporting the Active Server Pages interface. This means that the scripting code for this component may reference ASP-specific global objects (Response, Server, and so on). Although it is not explicitly used in this example, this is a useful feature of WSCs that should be noted.

<script> Element

Similar to <script> elements found in normal ASP and HTML pages, the script blocks in a WSC contain scripting code that implements the various methods, properties, and events that are exposed through the <public> element. The <script> tag supports a single attribute: the language attribute. This attribute determines which scripting processor will be used to interpret the script within the tag.

Because the WSC file is itself a valid XML document, the entire contents of the <script> block are normally enclosed in a CDATA block. Without the CDATA block, each occurrence of special XML characters (such as <, >, and &) would need to be escaped. Within a CDATA block, this is not necessary.

Implementing the ProcessOrder() Method

After the WSC framework has been built, validated, and successfully registered (either by right-clicking from the Windows shell or using regsvr32.exe), it is time to develop the scripting code for the component. This version of the component will be developed in VBScript; however, it could just as easily be written using JScript, Perl, or any other language available for the Windows Scripting Host.

The scripting code that makes up the implementation of the object will be written in the <script> block of Listing 15.1. The first line of the script (Option Explict) indicates that all variable names must be declared.

Based on the declared parameter list, and the fact that the ProcessOrder() method will return an order number, this will be the VBScript function signature:

Function ProcessOrder(strCustomerName, strCCNum, strEmailName,_
    strEmailDate, astrPartNums, astrQuantities)

The last two parameters are intended to contain arrays: the first an array of part numbers, the second an array of quantities. Because the scripts in a WSC are typeless, all parameters and variables are of the type Variant. No explicit restrictions are placed on what type of variable may be passed for any given argument. However, if a type mismatch occurs in the method code, a runtime error will be thrown.

The logic of the application will be familiar to most programmers who have written ADO applications in VBScript. First, an ADO Connection object will be created and used to open the ODBC data source for the order database:

Dim cn
Set cn = CreateObject("ADODB.Connection")
cn.Open "SXML-OrderDatabase"

After the connection has been opened, a SQL statement is constructed to insert incoming information into the Orders table in the database:

Dim strSQL
strSQL = "insert into Orders (strCustomerName, strCCNumber,"
strSQL = strSQL & " strSenderEmail, dtOrderSent) values ("
strSQL = strSQL & "'" & strCustomerName & "', '" & strCCNum & "'"
strSQL = strSQL & ", '" & strEmailName & "', '" & strEmailDate & "')"

This SQL statement is then executed (using the open ADO connection), and the unique ID of the new row is retrieved using the special @@identity variable that is associated with the connection:

cn.Execute strSQL

Dim idOrder
idOrder = cn.Execute("select @@identity")(0).Value

Now that the order ID is known, it is possible to insert each item that was passed in using the astrPartNums and astrQuantities arguments:

Dim i

For i = 0 To UBound(astrPartNums)
  strSQL = "insert into Items values (" & idOrder & ", '" & astrPartNums(i) & "'"
  strSQL = strSQL & ", " & astrQuantities(i) & ")"

  cn.Execute strSQL
Next

Finally, the connection can be closed, the return value of the method can be set, and the function ends:

  cn.Close
  Set cn = Nothing

  ProcessOrder = idOrder
End Function

Standalone Component Testing

Now that the component has been written and registered, it is a good idea to test and debug it in an isolated environment before attempting to execute it through the SOAP framework. The easiest way to do this is to create a simple script that can be executed using the Windows Scripting Host. Listing 15.2 shows the contents of StandaloneOrderHandlerTest.vbs, which is a simple script that instantiates an OrderHandler object and calls the ProcessOrder() method with some test arguments.

Listing 15.2. A standalone test script for an OrderHandler object.
Dim oh

Set oh = CreateObject("SXML.OrderHandler")
Dim idOrder
idOrder = oh.ProcessOrder("Customer One", "223234234",_
  "[email protected]", "2/2/01", Array("Q123", "B234"), Array(2, 5))
MsgBox "Order ID: " & idOrder

After the WSC file has been successfully registered (using regsvr32.exe, for example), this script may be executed either by double-clicking on it from the Windows shell, or from the command line by typing its name (in the directory where it is located):

c:SamsStrategicXMLChapter15Project>StandaloneOrderHandlerTest.vbs

After the order has been successfully added to the database, a Windows message box will appear with the new order ID in it.

Setting Up a SOAP Service

Now that the component has been developed and verified in a simple environment, it is time to make it available to SOAP clients. The first step is to install the Microsoft SOAP Toolkit on the Windows server that will host the SOAP application.

Installing the Microsoft SOAP Toolkit

The Microsoft SOAP Toolkit is available for download from the Microsoft Developer Network (MSDN) Web site. Before installing the toolkit, be sure to check the prerequisites and minimum system configuration to ensure that your system is compliant. SOAP runs as either an ISAPI plug-in or an ASP page. Either method provides the same functionality to SOAP clients.

After the SOAP toolkit has been installed, it is time to configure an IIS virtual directory that will contain the SOAP application files.

Creating a Virtual Directory

SOAP clients specify which SOAP service they want to invoke by connecting to a specific URL that is hosted on a SOAP-compliant server. Although it is possible to co-mingle SOAP and non-SOAP content in a single virtual directory, this application will isolate all SOAP-related content in a single IIS virtual directory called OrderHandler.

The examples and test scripts for this application assume that IIS is running on the local machine (that is, all URLs begin with http://localhost/). Create an empty subdirectory that will contain the SOAP-related gateway files, and share it using IIS as the OrderHandler sub directory of the IIS Default Web Site. This directory will contain the WSML and WSDL files that are used by the SOAP ISAPI plug-in to serve SOAP client requests.

Note

It is not necessary (and in fact quite insecure) to place the WSC component file (OrderHandler.wsc) in the OrderHandler virtual directory. The SOAP server will instantiate the object using the component's progid (SXML.OrderHandler). The COM framework deals with mapping that progid to a physical path, which means that the component may be located anywhere on the system. Also, security permissions must be considered when placing the component. The identity of the incoming SOAP request will be determined by the settings in the Directory Security tab of the IIS virtual directory properties dialog. If anonymous browsing is used to link to the SOAP directory, the anonymous user must have file-system permissions to read the WSC component file.


After the virtual directory has been set up, it is time to create the WSML and WSDL files that will be used by the SOAP server (and some SOAP clients) to call the OrderHandler object.

Using WSML and WSDL

To expose a COM object using the SOAP toolkit, it is necessary to provide two different XML documents that describe the SOAP service to be provided, as well as the concrete COM object methods that must be invoked. The close relationship between the WSML and WSDL files can be confusing at times, but the basic purpose of each is easy to understand.

The WSDL document exposes a set of generic SOAP services, bindings, ports, and messages for use by any SOAP client. It is a W3C-endorsed standard that is being promoted by Microsoft and other vendors as a standard way to expose programmatic services on the Web. It does not contain any Microsoft- or COM-specific information.

However, these generic declarations do not provide sufficient information for the SOAP server to actually process a request. To do this in a Windows framework, there must be some way to associate an actual COM object and specific method with each inbound SOAP message. This is the purpose of the WSML file. It defines which COM objects will service which incoming messages. It links the message elements from a SOAP request to specific methods in the requested COM object. Together, the WSDL and WSML files allow end-to-end processing of SOAP requests.

Writing the WSML File

In most of the literature associated with the Microsoft SOAP Toolkit, the WSDL file is explained before the WSML. Basically, the WSDL file lists the various abstract services and messages that the SOAP server supports, whereas the WSML file explains how to link these abstract requests to physical COM object instances and methods.

Note

Although the SOAP toolkit provides the WSDL/WSML Generator tool that can automatically generate these files for most COM objects, it will not work for our WSC-generated COM object. Because the ProcessOrder() method uses variants for all of its arguments, it is necessary to explicitly define the expected argument types for the SOAP framework.


The complete contents of OrderHandler.wsml are shown in Listing 15.3.

Listing 15.3. The WSML file for the OrderHandler SOAP service.
<servicemapping name='OrderHandler'>
  <service name='OrderHandler'>
    <using PROGID='SXML.OrderHandler' cachable='0'
      ID='OrderHandlerObject'/>
    <port name='OrderHandlerSoapPort'>
      <operation name='ProcessOrder'>
        <execute uses='OrderHandlerObject' method='ProcessOrder'>
          <parameter callIndex='1' name='strCustomerName'
              elementName='strCustomerName'/>
          <parameter callIndex='2' name='strCCNum'
              elementName='strCCNum'/>
          <parameter callIndex='3' name='strEmailName'
              elementName='strEmailName'/>
          <parameter callIndex='4' name='strEmailDate'
              elementName='strEmailDate'/>
          <parameter callIndex='5' name='astrPartNums'
              elementName='astrPartNums'/>
          <parameter callIndex='6' name='astrQuantities'
              elementName='astrQuantities'/>
          <parameter callIndex='-1' name='retval'
              elementName='Result'/>
        </execute>
      </operation>
    </port>
  </service>
</servicemapping>

The three major entities exposed in this file are service, ports, and operations. A service is linked to a public SOAP service that is exposed in a WSDL file using the name attribute of the <servicemapping> element. Within the <servicemapping> element, a <service> element contains all the information required to link the abstract SOAP messages declared in the WSDL file to concrete COM object instances and methods.

Within a <service> element, one or more <using> elements declare the COM objects that will be exposed and give hints about how they may be used. These are the three attributes used in this example:

  • PROGID— This is the COM progid of the object that must be instantiated.

  • cachable— This is a Boolean value that indicates whether the object instance may be cached by the SOAP service for use to serve multiple SOAP requests.

  • ID— This is the XML ID that will be used by subsequent <execute> elements to indicate which object their methods apply to.

The <port> element contains one or more <operation> elements that define specific COM methods that can be invoked by the SOAP server. The port name is a linkage between the SOAP port declared in the WSDL <portType> element and the COM object operations defined in the WSML file. There is a one-to-one mapping between operations declared in the WSML <port> element and operations declared in the WSDL <portType> element.

An operation contains an <execute> element that defines precisely which COM object and method should serve a particular request. The execute element must include a uses attribute that references a particular COM object through a <using> element that is declared within the current <service> element. The method attribute gives the method name within the object that should be invoked. The <execute> element must contain <parameter> elements that map between the COM method parameters and the SOAP message elements that are declared in the corresponding <message> element of the WSDL document.

Each <parameter> element links a particular element from a SOAP request to a parameter position in a COM object method invocation. The callIndex attribute is a one-based index that indicates which position the current parameter occupies in the parameter list. If it is –1, it represents the return value of the method. The name attribute is not actually used by SOAP at the present time, but for documentation and consistency purposes it should be set to the COM method parameter name. The elementName attribute maps to a <part> declaration of a <message> element defined in the WSDL file.

Now, having defined the concrete linkages in the WSML file, we need to define the abstract SOAP interfaces in the WSDL file.

Writing the WSDL File

A WSDL document enables a SOAP client to retrieve complete information about the services, operations, and message types that are supported by a particular SOAP server. The full details of the WSDL file format would require an entire chapter (if not another book), but by examining a concrete example it is possible to become productive rather quickly.

A WSDL document serves as a contract between the client and server so that each understands what is expected of the other. The types of SOAP entities that are exposed by the WSDL file are shown in Table 15.1.

Table 15.1. SOAP entities exposed in a WSDL document.
Entity Explanation
Service Is a named collection of related SOAP ports.
Port Defines the binding, port type, and physical URL that the client will use to transmit and receive SOAP requests for this service.
Binding Specifies the concrete encoding details (preferred character encoding, message element names, and so on) for a given SOAP port.
Port type Enumerates the various operations that can be performed over a particular SOAP port. An operation is equivalent to a single method call on an object.
Message Describes the logical structure of the content being transferred back and forth in a given SOAP request. Messages are composed of parts, which map an XML element name to a specific data type.
Types Is the section where application-specific types may be declared for use in message declarations. Types are declared using XML Schema notation.

To help clarify the linkages between the various parts of the WSDL and WSML documents, Figure 15.3 is a graphical representation of the contents of the two XML documents that shows the relationships between them.

Figure 15.3. WSDL and WSML document relationships.


The complete WSDL file for the OrderHandler service is located in OrderHandler.wsdl. It provides the declarations necessary to allow the Microsoft SOAP server to receive and process SOAP requests for the OrderHandler service. To complete the application setup, the WSDL and WSML files must be copied to the IIS virtual directory that was created previously. Then, it is time to test the SOAP connection to make sure that the system is properly configured from end to end.

Testing the SOAP Connection

To test the connection, a simple VBScript file will be used. It will use the Microsoft SOAP client object to open a connection to the server and call the ProcessOrder() method on the OrderHandler object. Listing 15.4 shows the contents of the SOAP test script in OrderHandlerSOAPTest.vbs.

Listing 15.4. The SOAP server test script.
Option Explicit

Dim soapClient
Set soapClient = CreateObject("MSSOAP.soapClient")

On Error Resume Next
soapClient.mssoapinit "http://localhost/OrderHandler/OrderHandler.wsdl",_
  "OrderHandler", "OrderHandlerSoapPort"

If Err <> 0 Then
  wscript.echo "initialization failed " + Err.description
End If

wscript.echo  soapClient.ProcessOrder("Customer One", "223234234",_
  "[email protected]", "2/2/01", Array("Q123", "B234"), Array(2, 5))
If err <> 0 Then
  wscript.echo   Err.description
  wscript.echo   "faultcode=" + soapClient.faultcode
  wscript.echo   "faultstring=" + soapClient.faultstring
  wscript.echo   "faultactor=" + soapClient.faultactor
  wscript.echo   "detail=" + soapClient.detail
End If

This script creates and initializes an instance of the Microsoft soapClient object. The URL location of the WSDL file is set to the local host, in the OrderHandler virtual directory. Besides specifying the location of the WSDL file, the mssoapinit() method also takes the name of the SOAP service requested as well as the port name (both items are declared in the WSDL file).

After the SOAP connection is successfully initialized, the ProcessOrder() operation is invoked with a set of test parameters. Notice that the Array() VBScript function is used to create the temporary arrays that contain the part numbers and quantities for the order. If an error occurs during the request, the script uses the wscript.echo() method to report it to the console. To run this script, either double-click it from the Windows shell or run it from the command line:

c:SamsStrategicXMLChapter15Project>cscript OrderHandlerSOAPTest.vbs

The cscript executable runs the script as a console script, which causes output to be echoed to standard output. If the script is run through the shell, the wscript.echo() method output will be displayed using a Windows message box.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.29.145