Anatomy of WSDL



Anatomy of WSDL

One of the more difficult roadblocks to understanding WSDL is the anatomy and structure of WSDL documents. It's difficult to address the requirements mentioned in preceding chapters (such as extensibility and abstract structures of message patterns) without potentially ending up with a difficult syntax to understand. The authors of WSDL decided to sacrifice a simple syntax for a more expressive and powerful one.

That said, once you become accustomed to the syntax, WSDL documents are fairly easy to read. Basically, WSDL is made up of several interesting sections, some of which are abstract and some of which are concrete.

Abstract Message Operations

The abstract pieces include the <types>, <message>, and <portType> sections. In those sections, you can describe in a WSDL document all of the data and operations that a Web service implements. Note that this information is completely nonspecific to SOAP. What we are getting is purely information about the data and the messages and the operations involved. Let's review what messages and operations mean.

Messages are pieces of data that are sent from one process to another. Operations are combinations of messages that express complete sets of related messages. That is the most abstract definition I can think of, but it's actually fairly specific. For example, you can send a message that is a purchase order from machine A to machine B, and then machine B can respond to machine A with a purchase order confirmation message.

Now, it's possible to describe this message in a completely abstract manner. Although you could include the semantic content of the message in this abstract description (such as the pieces of information that make up a purchase order), the actual message format, which would include information such as that it is using SOAP and HTTP, would still be unknown.

The power of this is that you then can specify multiple concrete ways of sending and receiving these messages! For example, you can define the purchase order operation abstractly, and then implement it with both SOAP/HTTP and ebXML.

Concrete Operation Information

The <binding> and <service> sections of the WSDL document specify all of the specific, concrete pieces of information needed to send the messages in any specific operation. Typically, this is formatting information, such as the SOAP enveloping schema, and possibly encoding information, such as that found in SOAP Section 5.

Concrete binding information usually also contains other nonformatting specifics, such as the service endpoint. Typically however, the actual location of a service will be found within the <service> element, which will refer to the <binding>.

Types

The <types> section of a WSDL document describes the data types that the rest of the WSDL document will reference. The WSDL specification is very flexible in terms of what this section can contain. And, you don't actually even need a <types> section.

Typically, and for maximum interoperability, the <types> section will contain an XML Schema 2001 document, as shown in Listing 10.3.

Listing 10.3 : The <types> Section of a WSDL Document
<types>
    <s:schema
          xmlns:s="http://www.w3.org/2001/XMLSchema"
          targetNamespace="http://keithba.com/Sample">
      <s:element name="UpdateCustomerRecord">
        <s:complexType>
          <s:sequence>
            <s:element name="ds" type="s:string">
            </s:element>
          </s:sequence>
        </s:complexType>
      </s:element>
    </s:schema>
</types>

Alternatively, you can have a <types> section that uses a different schema version, such as the 2000 version. You even can have both in the same WSDL document, as Listing 10.4 does.

Listing 10.4 : Mixing Schema Versions in a <types> Section
<types>
       <schema
              targetNamespace="http://keithba.com"
              xmlns="http://www.w3.org/2000/10/XMLSchema">
           <element name="StockRequest">
              <complexType>
                  <all>
                      <element name="Symbol" type="string"/>
                  </all>
              </complexType>
           </element>
       </schema>
    </types>

You can even use another schema language, such as Relax NG, as in Listing 10.5.

Listing 10.5 : Using a Non-XML Schema in the <types> Section
<types>
<element name="PurchaseOrderSubmission"
    xmlns="http://relaxng.org/ns/structure/1.0">
  <zeroOrMore>
    <element name="PurchaseOrder">
      <element name="ID">
        <text/>
      </element>
      <element name="Date">
        <text/>
      </element>
    </element>
  </zeroOrMore>
</element>
</types>

Or, you can omit the <types> section entirely:

<types /> 

If you do omit the <types> section, then when you want to refer to a piece of data when building messages, you can just directly refer to the primitive XSD type that makes up the message.

<message name="GetPriceOutput"> 
        <part name="body" element="xsd:string"/>
</message>

What's advantageous about this whole idea of using a <types> section is that it doesn't even have to be describing XML! WSDL specifically states that if you want to describe a Web service that contains non-XML data (maybe because you want to describe a pre-SOAP, or even pre-XML, protocol), then you still can define the data types and their structure using a schema in the <types> section.

Messages

The <message> sections of a WSDL define just that: messages. A message is a simple concept: a set of related data that point A sends to point B. A message is not a method (that's an operation), but more like a method call, or a method return.

NOTE

Remember that WSDL isn't just about remote procedure calls (RPCs). WSDL can describe RPCs, but it also can describe messages and operations. Messages and operations are similar to method calls and methods, but they are not the same.

You can split messages into parts to represent the logical pieces of the message. For example, here is a message with a single part:

<message name="HelloWorldInputMessage"> 
    <part name="body" element="s0:HelloWorld" />
</message>

And here is an example of a message with multiple parts:

<message name="HelloWorldOutputMessage"> 
    <part name="HelloPart" element="s0:HelloResponse" />
    <part name="WorldPart" element="s0:WorldResponse" />
</message>

In this example, I'm including two parts for an output message (not that anything in the XML here is proof that it is an output message): a part for the word "hello" and a part for the word "world."

Messages are referenced in the <portType> section, where they are composed together into complete operations.

Port Types and Operations

A port type is an abstract definition of an instance of a Web service. The <portType> section in a WSDL document is the most interesting and innovative piece of the WSDL architecture. Although it too is merely an <abstract> section, it wraps up all of the preceding <abstract> sections. The <portType> section contains a set of related operations. These operations, in turn, are groups of related sets of messages. Typically, you will see operations that specify an input message and an output message, which is very RPC-like, as well as very HTTP-like.

But, this isn't the only way you can group messages into an operation. WSDL defines four different transmission types:

  • One-way

  • Request–response

  • Solicit–response

  • Notification

One-way operations are simple: A single message is sent from one point to another, and there is no logical message response for the operation. This is one of two operation types that ASP.NET Web Services supports, and can be quite useful.

The other operation type that ASP.NET supports is the requestresponse primitive. This is the default with .NET, and by far the most popular operation type found in any Web service platform. Basically, it states that point A will send a message, and then point B will reply with a related message over the same channel.

Solicit–response operations don't map quite as well to the way we are accustomed. Basically, solicit–response is like request–response, but backward: The endpoint referred to in the WSDL is the one that sends the first message, and then point A would send a response to point B.

Notification operations are much like events. The idea is that notification is an inverse one-way operation. The service sends the messages. Notifications work well for mapping operations to programmatic events.

NOTE

I don't know of any Web services that use operation types other than one-way and request–response. I think it's a safe bet to focus on those two operation types in your Web service design.

Listing 10.6 shows an example of a typical <portType> section that contains a couple of operations, one that is one-way and another which is request–response.

Listing 10.6 : The <portType> Section of a WSDL Document
<portType name="TestDemoSoap">
    <operation name="HelloWorld">
      <input message="s0:HelloWorldSoapIn" />
      <output message="s0:HelloWorldSoapOut" />
    </operation>
    <operation name="Hello">
      <input message="s0:HelloSoapIn" />
    </operation>
</portType>

Bindings

Bindings are where the abstract information that the WSDL contains starts to become concrete. Specifically, the <binding> section contains specific protocol information conveyed with extensions elements. (Remember, WSDL allows for elements from other namespaces in many places.) Bindings are among the places where you want more specific information.

Because SOAP is the protocol of choice, the WSDL specification details the extension elements that can specify SOAP information, namely, the

  • Transport that the SOAP messages will use.

  • Style of the operations.

  • Encoding use of the operations.

  • SOAPAction.

If you remember the requirements from earlier in this chapter, then you'll notice that the SOAP binding is where a lot of this information (such as the SOAPAction value) is defined. Listing 10.7 shows an example SOAP binding.

: The SOAP Binding Section of a WSDL Document
<binding name="TestDemoSoap" type="s0:TestDemoSoap">
    <soap:binding
         transport="http://schemas.xmlsoap.org/soap/http"
         style="document" />
    <operation name="HelloWorld">
      <soap:operation
        soapAction="http://Keithba.com/HelloWorld"
        style="document" />
      <input>
        <soap:body use="literal" />
      </input>
      <output>
        <soap:body use="literal" />
      </output>
    </operation>
    <operation name="Hello">
      <soap:operation
         soapAction="http://KeithBa.com/Hello"
         style="document" />
      <input>
        <soap:body use="literal" />
      </input>
    </operation>
  </binding>

Services and Ports

Because we have something called port types, it probably isn't too surprising that a port element exists within WSDL. Port elements define the actual endpoint of a service.

<port name="TestDemoSoap" binding="s0:TestDemoSoap"> 
      <soap:address location="http://localhost/test/testdemo.asmx" />
 </port>

Notice that for SOAP, you need an extension element to refer to the location correctly. This is because other protocols may have entirely different ways to refer to locations and endpoints for the service.

The service element is used to group ports together. Not too interesting, but still needed:

<service name="TestDemo"> 
  <port name="TestDemoSoap" binding="s0:TestDemoSoap">
    <soap:address location="http://localhost/test/testdemo.asmx" />
  </port>
</service>