Let’s say that you decide to tell your friend about a cool new Web site. To do that, you give the friend the URL and the reason why the Web site is interesting. In a Web services world, there is no simple way to tell a computer that a cool Web service exists at a specific location. The problem is that the computer requires specific details, and a human, typically, does not provide enough details. That is the purpose of WSDL (Web Services Description Language). WSDL makes it possible to describe a Web service so that a computer program can take the WSDL information and configure specific pieces of Web service infrastructure. WSDL is to Web services what schema information is to XML files.
A WSDL document defines five aspects of the SOAP message, which are defined as follows:
XML types: It is possible to define the XML type of the various elements of the SOAP message. This makes it possible to verify the correctness of the data sent and/or received.
Message description: A SOAP message is concatenation of various logical message sections. Consider an individual SOAP message as a chapter in a book and the logical part as a paragraph within the chapter.
Port type: As a programmer, you might think port means logical device port. Instead, the port type means a combination of input and output messages. Continuing the book metaphor, think of the port as one of the book’s parts, or sections, that contains individual chapters.
Binding: Defines the specific format of the port type, such as protocol or data binding. Think of the binding as the entire book, including pictures, chapters, and so on.
Service: Used to define the service, which implies that the Service tag is the entry point and puts everything together for processing.
In a nutshell, what you need to remember is that a WSDL defines the SOAP message as an abstract entity that can be correlated to some business logic. WSDL is not just a definition of the SOAP message, because that requires only the XML types. WSDL is a way of describing what the Web service does. You could say that WSDL adds the object-oriented aspect to SOAP.
WSDL can become complex very quickly; therefore, the focus here is on simple WSDL. The complexity of WSDL is not algorithmic but results from information overload due to the large number of elements that can be defined. Take another look at the SOAP message shown earlier:
<?xml version="1.0" ?> <env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope"> <env:Body> <math:add xmlns:math="http://www.devspace.com/2002/1/math"> <math:num>1</math:num> <math:num>1</math:num> </math:add> </env:Body> </env:Envelope>
In the following sections, I use this SOAP message and show you how to create a WSDL file incrementally. This method should help you understand where to start when developing your own WSDL files.
The first thing you need to do is define the various XML types present in this message. In SOAP, different encodings and XML types can be used. However, the specification clearly prefers using XML Schema data types because this ensures maximum interoperability and broadest support. Converting the previous SOAP message into WSDL type definitions yields the following XML:
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema” targetNamespace=”http://www.devspace.com/2002/1/math” elementFormDefault=”qualified”> <xs:element name=” add”> <xs:complexType> <xs:sequence> <xs:element name=”num” ref=”num” minOccurs=”1” maxOccurs=”unbounded”/> </xs:sequence> <xs:attribute name=” math” type=”xs:anyURI” use=”required”/> </xs:complexType> </xs:element> <xs:element name=” num”> <xs:simpleType> <xs:restriction base=”xs:byte”> <xs:enumeration value=”1”/> <xs:enumeration value=”2”/> </xs:restriction> </xs:simpleType> </xs:element> </xs:schema>
The previous schema definition is a self-encapsulation section of XML and can be used to validate the XML validity of the SOAP message within the SOAP Body tag. Pay special attention to the targetNamespace attribute. Notice that it has the same value as the math namespace definition within the SOAP message. This is intentional and provides the cross-reference between the SOAP Body contents and the schema.
The next item that you have to define is the message that is being sent and its logical WSDL part. With respect to the SOAP message, the following XML is defined:
<wsdl:message name=”msgAdd”> <wsdl:part name=”main” element=”mathxsd:add”/> </wsdl:message> <wsdl:message name=”msgAddResponse”> <wsdl:part name=”main” element=”mathxsd:addResponse”/> </wsdl:message>
The XML tag message identifies that a message with the name msgAdd and another message with the name msgAddResponse are being defined. Specifically what is happening is that two SOAP messages are being defined based on the elements mathxsd:add and mathxsd:addResponse. The element attribute references the mathxsd namespace that has not yet been defined. This definition has been omitted because the various WSDL pieces have not yet been put together in one XML document. The mathxsd is a namespace that references the schema type information defined in previously.
In the defined message msgAdd, there is only one part named main, which is abstract identifier. There could be multiple parts, with each part being a separate document within the XML SOAP Body. Consider the following SOAP message:
<env:Envelope xmlns:env=”http://www.w3.org/2001/12/soap-envelope”> <env:Body> <math:add xmlns:math=”http://www.devspace.com/2002/1/math”> <math:num>1</math:num> <math:num>1</math:num> </math:add> <math:subtract xmlns:math=”http://www.devspace.com/2002/1/math”> <math:num>1</math:num> <math:num>1</math:num> </math:subtract> </env:Body> </env:Envelope>
The preceding example contains two embedded XML documents. The first XML document is math:add and the second is math:subtract. In terms of a WSDL message, it could be defined as follows:
<wsdl:message name="formulaRequest"> <wsdl:part name="step1" element="mathxsd:add"/> <wsdl:part name="step2" element="mathxsd:subtract"/> </wsdl:message>
In the WSDL you add two parts to the newly defined formulaRequest message, which are add and subtract. You do this so that the infrastructure can separate the SOAP message into two sections, each of which does its own processing. In this example, the infrastructure can create an add and subtract processor.
Another way of illustrating these two parts is to collapse them into one part and then, within the XML types, define a complex schema type that is, in essence, identical to the WSDL above. This redundancy is purely logical and business-related.
The port type of a SOAP message has nothing to do with a socket port. A WSDL port type is a way of describing an interaction between the sender and receiver of the SOAP message. The SOAP specification only says there is a one-way message exchange. Sending a response just happens to be yet another message exchange. Using WSDL, it is possible to define exactly what will be sent and received. This is very important. Consider the case of sending a SOAP message using SMTP. With SMTP it is not possible to get an answer right away and, hence, a waiting SOAP sender will wait indefinitely. Using WSDL as the infrastructure, you can determine if a response will be sent and when. But do not consider the port type as a physical definition of SOAP message exchange. The port type defines an abstract message exchange mechanism. The specifics are defined in the bindings, which have not yet been discussed.
In the previous WSDL message descriptions, the methods msgAdd and msgAddResponse were defined. Both of these methods tie together to form a request and response action. In terms of a port type, the WSDL is defined as follows:
<wsdl:portType> <wsdl:operation name=”portAddingNumbers”> <wsdl:input name=”Adding” message=”msgAdd”/> <wsdl:output name=”Result” message=”msgAddResponse”/> </wsdl:operation> </wsdl:portType >
The root of a port type is the operation XML tag. Within the operation XML tag are a number of input and output XML tags. The exact number is based on the operation being performed. Although XML can define many input and output operations, the WSDL specification has not yet achieved that level of complexity. Instead, the WSDL defines the following four types of logical operations that can be performed:
One-Way Operation: The sender sends a SOAP message to the receiver, and does not expect a response.
Request-Response Operation: The sender sends a SOAP message to the receiver, and the receiver sends a response to the message.
Solicit-Response Operation: The receiver sends a SOAP message to the sender, and the sender sends a response. If this sounds confusing, consider this nothing more than an asynchronous callback using SOAP.
Notification Operation: The receiver sends a SOAP message to the sender, and the receiver does not expect an answer. This could also be called a targeted broadcast in SOAP terms.
The portAddingNumbers port type is an example of a Request-Response Operation in that it contains an input and output XML tag. The name attribute defines an abstract identifier of the step being carried out. The message attribute is a cross-reference with a previously defined WSDL message. In the Request-Response Operation, there cannot be more input or output tags. What is optional is the fault XML tag. The fault XML tag identifies a SOAP response containing a specific fault message.
The One-Way Operation can contain only one input tag. The Solicit-Response Operation contains the same tags as the Request-Response Operation, except that the order is different. In the Request-Response Operation, the order of the input and output tags is input first and output second. In the Solicit-Response Operation, the order is output first and then an input tag. In either case, the fault tag is optional. But in the Solicit-Response Operation, the fault tag is generated by the sender. And in the final Notification Operation, only an output tag is sent by the receiver. Note that there is no optional fault tag with either the One-Way Operation or the Notification Operation. The message exchange, in this case, is one way, and it is assumed that the message could disappear into the never-never land.
Binding is a bit more complicated because it throws everything into question that you have learned thus far. The binding aspect is necessary, and it needs to be kept generic, but it also means that SOAP is not part of the binding. Up to this point, the discussion has centered around SOAP being used to exchange messages. What if something else is being used? Thus far, the WSDL items, XML types, message, and port type have been defined. Could these WSDL items be used for generic XML or XML-RPC? The answer is a definite yes because none of these items is specific to the SOAP format. Instead, the various items refer to the abstract problems that SOAP solves.
You can define a binding element in various, nonspecific ways. Here is a simple example:
<binding name="BindingAddition" type="portAddingNumbers"> <operation name="AddSomeNumbers"> <input message="add"> </input> </operation> </binding>
Looking at this example, you can see something odd is occurring. The binding references the port type using the attribute type. But yet within the binding tag there is another operation tag with an input tag. What does this imply? Does this imply there is no need to define the port type portAddingNumbers? The answer is WSDL allows overloading and overriding. In the port type definition, the logical operations are defined, but in the binding the specifications regarding the operation are defined.
So for example, the following SOAP bindings could be associated with the simple binding:
<binding name=”bindingAddition” type=”portAddingNumbers”> <soap:binding style=”rpc” transport=”http://schemas.xmlsoap.org/soap/http”/> <operation name=”AddSomeNumbers”> <soap:operation soapAction=”http://www.devspace.com/add”/> <input message=”add”> <soap:body use=”encoded” namespace=”http://example.com/stockquote” encodingStyle= “http://schemas.xmlsoap.org/soap/encoding/”/> </input> </operation> </binding>
In this case, the bindings that deal with SOAP are using the soap namespace. The SOAP binding is specified by adding the XML binding tag, with a predefined style attribute of rpc and the transport attribute named to HTTP. The style and transport attributes are specific to the SOAP binding and are not usually included. What you do need to specify is the XML binding tag. It is prefixed by the namespace of the binding, which could be SOAP or HTTP. The MIME binding is a bit of an oddity because it is usually used in conjunction with another binding. The point, though, is that the XML binding tag or others are linked to the namespace.
Within the WSDL operation tag, there is a SOAP operation tag. The SOAP operation tag has the one attribute named soapAction. The attribute soapAction is special because it is used as an HTTP header addition, which is used by the HTTP binding to identify which part of the infrastructure will process the SOAP request. Adding the soapAction attribute may seem redundant with the addition of namespaces to the SOAP request. But the soapAction attribute makes it possible for SOAP intermediaries to process part of the SOAP message without actually processing the entire SOAP message. Within the WSDL input tag, there is a SOAP Body tag. The SOAP Body tag is used to indicate how the message will be encoded and the namespace used to identify the SOAP message.
Now back up a bit to where the WSDL operation and input tags seemed redundant because they are already specified by the port type portAddingNumbers. The port type is an abstract operation, used to define how messages will be sent back and forth. But those messages can be sent using different protocols (HTTP, SMTP) and different message types (SOAP, HTTP). By adding the specifics to the port type, separating the protocol from the message type is more complicated Introducing the WSDL binding tag makes it possible to cross-reference a logical operation to a specific binding and Internet protocol.
The last item to define in a WSDL file is the service itself. The service provides the entry point to the WSDL file. From the service definition, it is possible to figure out what is being defined and how it is to be used. The following code shows a sample WSDL service definition:
<service name=”MathService”> <documentation>Want to add numbers? Here it is</documentation> <port name=”AddNumbersPort” binding=”tns:bindingAddition”> <soap:address location=”http://www.devspace.com.com/addnums”/> </port> </service>
The service is defined by the XML service tag, with the name attribute being a unique name to identify the Web service. The XML documentation tag is used for the first time. I avoided using this tag, but it is optional at every major WSDL item type. The documentation tag makes it possible to provide generic documentation that can be displayed using a tool. Note that the documentation tag should not be confused with the XML comment tag. The documentation tag is for application processing and display. Within the WSDL service tag is the port tag. The port tag is responsible for providing a physical binding to the binding defined by bindingAddition. In our binding example SOAP and HTTP were used, but the address where the service was located was not provided. The SOAP address_location tag provides the physical address. Again, this is an abstraction to make it simpler to separate and reuse various WSDL definitions.
The individual pieces of the WSDL have been defined, and now it is time to put everything together into one WSDL file. The example is defined as follows:
<definitions name="MyAdditionExample" targetnamespace="http://www.devspace.com/addition.wsdl" xmlns:tns=" http://www.devspace.com/addition.wsdl" xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" xmlns:xsd1=" http://www.devspace.com/2002/1/math" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/"> ...<!--Put everything in here--> </definitions>
The individual elements that were defined can simply be cut and pasted into the area where the XML comment says Put everything in here. The only issue is to make sure that the namespaces are correct. WSDL and SOAP are very namespace heavy, so namespace accuracy requires careful attention.
To keep things simple, you should cut and paste the preceding namespaces, except for the following changes:
targetnamespace: This defines the namespace of your WSDL file locally and should be a unique identifier.
xmlns:tns: This is the same namespace as targetnamespace, except that the namespace is being assigned to a prefix.
xmlns:xsd: This is the namespace definition of your types defined in terms of a schema file, as the one defined in the types section of the WSDL file.
Another thing to remember when creating WSDL files is to stick with the same namespace prefixes. This makes it simpler to create and debug the various WSDL files.
To keep smaller WSDL files and make it possible to reuse different files, import sections into your WSDL file so that the definitions do not need to be re-created. Here’s an example of importing XML content into a WSDL file:
<definitions name=”MyAdditionExample”> <import namespace=” http://www.devspace.com/2002/1/math” location=”http://www.devspace.com/math/math.xsd”/> ... </definitions>
Finally, the last question is: Do you create WSDL files by hand or have a tool to generate them? The answer is: Who cares? WSDL files are going to be created once and kept forever. The one problem with SOAP is that you cannot change it. Let me explain. On another platform, there is something called DLL hell. DLL hell is when a program does not work after the DLL has been upgraded. DLL hell only exists on individual desktops. Imagine a popular SOAP service that, when the WSDL is changed once, causes all clients to crash. The point here is that the creation of WSDL is not a point-and-click operation; generally, pointing and clicking means that you don’t have to think much. (You get too excited about getting something done quickly.)
The last piece of WSDL that you need to consider is the bindings. You need to know what the individual tags imply. There are two major binding types—SOAP and HTTP—and they are explained in the following sections. SOAP is a binding mechanism you already know. But HTTP is different. Although SOAP can use HTTP to transport the message, the HTTP binding is aimed at solving the problem of the Web client communicating within the Web service infrastructure.
In previous examples, I have illustrated the SOAP binding, but I discuss it again here for reference purposes:
soap:binding: This tag is defined within the WSDL binding tag and specifies that the message is bound to the SOAP protocol. There are two attributes that can be used. The first attribute is transport and defines the protocol that can be used. Examples include http://schemas. xmlsoap.org/soap/http and http, ftp, and so on. In fact, this can be anything that the infrastructure can recognize. The second attribute is style, which can be either RPC or document. The style attribute is used for encoding purposes.
soap:operation: This tag is defined within the WSDL binding::operation tag to indicate how to process the SOAP message. There are two attributes: style and soapAction. The soapAction attribute can be considered an abstract identifier used to process the SOAP message. The style attribute can be either RPC or document, with the same intent as defined in the soap:binding attribute.
soap:body: This tag is the most varied and defines the encoding style of the SOAP message. For example, if the SOAP message is in RPC format, the tag order occurs in a specific pattern.
soap:fault: This tag is identical in function and purpose to soap:body, except that the tag applies when there is an error.
soap:header/soap:headerfault: Defines the extra SOAP headers that can be sent with the request.
soap:address: Defines the actual SOAP address request where the SOAP message is to be sent, which specifies a URI. There can be only one URI.
A client cannot use a Web browser to make SOAP calls. Writing another client so that you can make SOAP calls is just plain silly because you have the wonderful Web browser. To make the Web browser part of the Web services infrastructure, a specific binding has been developed called HTTP binding. The HTTP binding makes it possible for a Web browser to make Web service requests that are part of a bigger chain. The binding attributes are most likely added to the WSDL binding and service tags.
Here’s an example of processing the Add request using an HTTP form and HTTP POST. The appropriate HTTP POST data is as follows:
The corresponding WSDL with HTTP binding would then be as follows:
<binding name=”WebAddNumbers” type=”portAddingNumbers”> <http:binding verb=”POST”/> <operation name=”postAdd”> <http:operation location=”/formAdd.cgi”/> <input> <mime:content type=”application/x-www-form-urlencoded”/> </input> <output> <mime:content type=”text/html”/> </output> </operation> </binding>
The HTTP binding is specified by the prefix http, and the binding tag has the verb attribute. The infrastructure uses the verb to know how the request will be made. In this case, it is an HTTP POST. Within the WSDL operation tag, the http operation is defined with a specific location where the request will be made. Note that the location is not an absolute address. The location is appended to the address located in the WSDL service and HTTP address definition.
What is new in this WSDL is the MIME binding type identified by the mime prefix. The MIME binding is not a binding in the HTTP and SOAP sense. Instead the MIME binding can be considered as a way of defining how data is encoded using something other than XML. In this case, the MIME bindings specify for the input that the data will arrive as the MIME type application/x-www-form-urlencoded. The output is encoded as text/html.