Monday, 5 March 2012

WSDL (Web Service Description Language) - Complete Overview

The aim of this article is to describe what WSDL is, how we can utilise the technology from a development perspective and dive into technical detail on how the technology fits together and what is possible. This is an initial draft, but I will be updating it casually over the next few weeks. I have an example Math WSDL file provided by Microsoft throughout this article (Full appendix at the bottom of this post).


WSDL 1.1 (Web Service Description Language)

A WSDL file is an XML file which describes its associated web service. The WSDL XML file describes: where the web service is located, the methods available, parameters required and their return types. WSDLs are platform in-specific and can be consumed from any accessible environment, framework and/or language (Mac/Windows/Linux, Web Apps/Services, C#/C++/Python/Perl etc...)

Using the WSDL file, a consumer has enough information to query the underlying web services using one or many of it's associated operations. Most languages/frameworks have built-in or third party libraries available that can generate proxy classes based on the WSDL file (Another layer in front of the WSDL/Service you can query against using your chosen language. I.e. wsdl.exe for .NET or WSDL2Java for Java). This is only an option to make things easier, and is by no means mandatory.



Version History

WSDL 1.0 was introduced in 2000 and was developed through a collaboration by Microsoft, IBM and Ariba. The language was formalized in 2001 as version 1.1.

WSDL 2.0 became a W3C recommendation on June 2007. WSDL 1.2 was renamed to WSDL 2.0 because it has substantial differences from WSDL 1.1. The changes are:

Adding further semantics to the description language
Removal of message constructs
No support for operator overloading
PortTypes renamed to interfaces
Ports renamed to endpoint.
Offers binding to all HTTP Request methods (Not just GET and POST [WSDL 1.1]).. So it enabled better RESTful web services.

Most third-party vendors, however, have not adapted their offerings to support WSDL 2.0. For example, the Web Services Business Process Execution Language (WS-BPEL) uses WSDL 1.1.




Document Structure (One or many of these base four definitions may exist)

Code Snippet
  1. <definitions>
  2.  
  3. <types>
  4.   The data types used by the web service
  5. </types>
  6.  
  7. <message>
  8.   The messages used by the web service
  9. </message>
  10.  
  11. <portType>
  12.   The operations performed by the web service
  13. </portType>
  14.  
  15. <binding>
  16.   The communication protocols used by the web service
  17. </binding>
  18.  
  19. <service>
  20.   Information regarding the service endpoints.
  21. </service>
  22.  
  23. </definitions>
End of Code Snippet



Note:
- A WSDL can contain extension elements. For example, it is also possible to group multiple services into one WSDL. However, the core principles behind the technology remain the same.
- It is common for one or many type, mesaage, portType or binding definitions to exist within one WSDL file.




Port Types (Interfaces in 2.0)

The portType section defines all operations available within the web service. It also defines the input, output and fault messages for each operation (A fault tag can only exist with an output tag). The input/output/fault message names are mapped onto message tag names, which describe the names and types of parameters used.

Example

Code Snippet
  1. <message name="AddMessage">
  2. <part name="parameter" element="ns:Add"/>
  3. </message>
  4. <message name="AddResponseMessage">
  5. <part name="parameter" element="ns:AddResponse"/>
  6. </message>
  7. <message name="AddFaultMessage">
  8. <part name="parameter" type="ns:String"/>
  9. </message>
  10.  
  11.  
  12. <portType name="MathInterface">
  13. <operation name="Add">
  14. <input message="y:AddMessage"/>
  15. <output message="y:AddResponseMessage"/>
  16. <fault message="y:AddFaultMessage"/>
  17. </operation>
  18. <operation name="Subtract">
  19. <input message="y:SubtractMessage"/>
  20. <output message="y:SubtractResponseMessage"/>
  21. <fault  message="y:SubtractFaultMessage"/>
  22. </operation>
  23. <operation name="Multiply">
  24. <input message="y:MultiplyMessage"/>
  25. <output message="y:MultiplyResponseMessage"/>
  26. <fault  message="y:MultiplyFaultMessage"/>
  27. </operation>
  28. <operation name="Divide">
  29. <input message="y:DivideMessage"/>
  30. <output message="y:DivideResponseMessage"/>
  31. <fault  message="y:DivideFaultMessage"/>
  32. </operation>
  33. </portType>
End of Code Snippet


The above example defines a single portType/Interface with four operations (Add, Subtract, Multiply and Divide). These are all Request-response type operations (because they have input and output) that also include faults.

There are four different types of MEPs (Message exchange patterns) that exist when defining operations in WSDL files...


One-way
- Contains only an input message.

Request-response
- Contains an input message, followed by an output message (may contain a fault message)

Solicit-response
- Contains an output message, followed by an input message (may contain a fault message)

Notification
- Contains only an output message.


I will cover messages later in this article, but I have displays the tags here (For the Add operation only) to see how operations are mapped onto messages. AddFaultMessage takes a simple string type, however, complex types (Arrays, Lists, Custom Objects etc..) may exist which require definition in the Types section of the WSDL. Lets have a look at this next...




Types

The types section defines the data types that are used by the service. If the service uses only simple types I.e. Integers, Strings etc... then the types section is not required. WSDL types can also be reused across multiple services. The types section contains one or many schema tags. XML Schema's are the typical choice, however, WSDL 1.1 is not limited to this schema type.


Example

Code Snippet
  1. <types>
  2. <schema targetNamespace="http://example.com/weather.xsd" xmlns="http://www.w3.org/2000/10/XMLSchema">
  3. <xs:complexType name="MathInput">
  4. <xs:sequence>
  5. <xs:element name="x" type="xs:double"/>
  6. <xs:element name="y" type="xs:double"/>
  7. </xs:sequence>
  8. </xs:complexType>
  9. <xs:complexType name="MathOutput">
  10. <xs:sequence>
  11. <xs:element name="result" type="xs:double"/>
  12. </xs:sequence>
  13. </xs:complexType>
  14. <xs:element name="Add" type="MathInput"/>
  15. <xs:element name="AddResponse" type="MathOutput"/>
  16. <xs:element name="Subtract" type="MathInput"/>
  17. <xs:element name="SubtractResponse" type="MathOutput"/>
  18. <xs:element name="Multiply" type="MathInput"/>
  19. <xs:element name="MultiplyResponse" type="MathOutput"/>
  20. <xs:element name="Divide" type="MathInput"/>
  21. <xs:element name="DivideResponse" type="MathOutput"/>
  22. </xs:schema>
  23. </types>
End of Code Snippet



From our previous example, we can see that all four operations map to eight messages (one input, one output, four operations). These 8 messages map on to these eight elements defined in the Types section. Above these elements, you can see two complex types have been defined: MathInput and MathOutput. When contrasting these examples in terms on O-O programming, you can think of a complexType as an Object; and x and y as properties of this object.





Messages (Do not exist in WSDL 2.0 - Operations refer to types directly)

Messages define the input and output of operations. They either map onto an element or a type (Both defined within the Types section). As discussed within the portType section previously, the operation decides which message is used for it's input and output.

Code Snippet
  1. <message name="AddMessage">
  2. <part name="parameter" element="ns:Add"/>
  3. </message>
  4. <message name="AddResponseMessage">
  5. <part name="parameter" element="ns:AddResponse"/>
  6. </message>
  7. <message name="SubtractMessage">
  8. <part name="parameter" element="ns:Subtract"/>
  9. </message>
  10. <message name="SubtractResponseMessage">
  11. <part name="parameter" element="ns:SubtractResponse"/>
  12. </message>
End of Code Snippet



Bindings

Bindings provides specific details on how the portType section will actually be transmitted over the wire. The bindings can be made available via. multiple transports: HTTP GET, HTTP POST and/or SOAP.

You can specify multiple bindings for a single portType. I.e. Making an operation available via GET, POST and SOAP.

The following example illustrates a SOAP/HTTP binding for the MathInterface portType (Defined above)...


Example


Code Snippet
  1. <definitions
  2. xmlns="http://schemas.xmlsoap.org/wsdl/"
  3. xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  4. xmlns:xs="http://www.w3.org/2001/XMLSchema"
  5. xmlns:y="http://example.org/math/"
  6. xmlns:ns="http://example.org/math/types/"
  7. targetNamespace="http://example.org/math/">
  8. ...
  9. <binding name="MathSoapHttpBinding" type="y:MathInterface">
  10. <soap:binding style="document"
  11. transport="http://schemas.xmlsoap.org/soap/http"/>
  12. <operation name="Add">
  13. <soap:operation soapAction="http://example.org/math/#Add"/>
  14. <input>
  15. <soap:body use="literal"/>
  16. </input>
  17. <output>
  18. <soap:body use="literal"/>
  19. </output>
  20. <fault>
  21. <soap:body use="literal"/>
  22. </fault>
  23. </operation>
  24. ...
  25. </binding>
  26. ...
  27. </definitions>
End of Code Snippet



Binding Info
- The NAME of the binding must be given a unique name. I.e. MathSoapHttpBinding - so it can be referenced from within the WSDL.
- The TYPE of the binding must map onto the name of the portType (Interface WSDL 2.0)

soap:binding Info
- This element indicates that this is a SOAP 1.1 binding.
- The style of service is "document" (See section below on WSDL Styles)
- The transport protocol is HTTP
- The soap:operation element defines the SOAPAction HTTP header value for each operation
- The soap:body element defines how the message parts appear inside of the SOAP Body element (possible values include literal or encoded)




WSDL Styles


A WSDL SOAP binding can be either a Remote Procedure Call (RPC) style binding or a document style binding. A SOAP binding can also have an encoded use or a literal use.

Using document style in SOAP indicates that the body will contain an XML document, and that the message parts specify the XML elements that will be placed there. Using rpc style in SOAP indicates that the body will contain an XML representation of a method call and that the message parts represent the parameters to the method.

This gives you four style/use models:

RPC/encoded
RPC/literal
Document/encoded
Document/literal


The use attribute specifies the encoding that should be used to translate the abstract message parts into a concrete representation. In the case of 'encoded', the abstract definitions are translated into a concrete format by applying the SOAP encoding rules. In the case of 'literal', the abstract type definitions become the concrete definitions themselves (they're 'literal' definitions). In this case, you can simply inspect the XML Schema type definitions to determine the concrete message format. For example, the Add operation for the above document/literal binding looks like this on the wire:

Using literal definitions is much cleaner and easier for the tools to get right. Using the encoding rules has led to significant interoperability problems across toolkits. It also leads to weird situations like not being able to validate the wire-level message against the original schema definition (since it's abstract and not a true representation of the message)

More info on WSDL Styles here: http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/



Service


The service element defines a collection of endpoints/ports that expose our bindings (Listed above). Each port must be given a name and assigned a binding.

Example

Code Snippet
  1. <definitions
  2. xmlns="http://schemas.xmlsoap.org/wsdl/"
  3. xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  4. xmlns:xs="http://www.w3.org/2001/XMLSchema"
  5. xmlns:y="http://example.org/math/"
  6. xmlns:ns="http://example.org/math/types/"
  7. targetNamespace="http://example.org/math/">
  8. ...
  9. <service name="MathService">
  10. <port name="MathEndpoint" binding="y:MathSoapHttpBinding">
  11. <soap:address
  12. location="http://localhost/math/math.asmx"/>
  13. </port>
  14. </service>
  15. </definitions>
End of Code Snippet



Full WSDL Example (For all above examples)

Code Snippet
  1. <definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
  2. xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  3. xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
  4. xmlns:xs="http://www.w3.org/2001/XMLSchema"
  5. xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
  6. xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
  7. xmlns:y="http://example.org/math/"
  8. xmlns:ns="http://example.org/math/types/"
  9. targetNamespace="http://example.org/math/">
  10. <types>
  11. <xs:schema targetNamespace="http://example.org/math/types/"
  12. xmlns="http://example.org/math/types/"
  13. elementFormDefault="unqualified" attributeFormDefault="unqualified">
  14. <xs:complexType name="MathInput">
  15. <xs:sequence>
  16. <xs:element name="x" type="xs:double"/>
  17. <xs:element name="y" type="xs:double"/>
  18. </xs:sequence>
  19. </xs:complexType>
  20. <xs:complexType name="MathOutput">
  21. <xs:sequence>
  22. <xs:element name="result" type="xs:double"/>
  23. </xs:sequence>
  24. </xs:complexType>
  25. <xs:element name="Add" type="MathInput"/>
  26. <xs:element name="AddResponse" type="MathOutput"/>
  27. <xs:element name="Subtract" type="MathInput"/>
  28. <xs:element name="SubtractResponse" type="MathOutput"/>
  29. <xs:element name="Multiply" type="MathInput"/>
  30. <xs:element name="MultiplyResponse" type="MathOutput"/>
  31. <xs:element name="Divide" type="MathInput"/>
  32. <xs:element name="DivideResponse" type="MathOutput"/>
  33. </xs:schema>
  34. </types>
  35. <message name="AddMessage">
  36. <part name="parameters" element="ns:Add"/>
  37. </message>
  38. <message name="AddResponseMessage">
  39. <part name="parameters" element="ns:AddResponse"/>
  40. </message>
  41. <message name="SubtractMessage">
  42. <part name="parameters" element="ns:Subtract"/>
  43. </message>
  44. <message name="SubtractResponseMessage">
  45. <part name="parameters" element="ns:SubtractResponse"/>
  46. </message>
  47. <message name="MultiplyMessage">
  48. <part name="parameters" element="ns:Multiply"/>
  49. </message>
  50. <message name="MultiplyResponseMessage">
  51. <part name="parameters" element="ns:MultiplyResponse"/>
  52. </message>
  53. <message name="DivideMessage">
  54. <part name="parameters" element="ns:Divide"/>
  55. </message>
  56. <message name="DivideResponseMessage">
  57. <part name="parameters" element="ns:DivideResponse"/>
  58. </message>
  59. <portType name="MathInterface">
  60. <operation name="Add">
  61. <input message="y:AddMessage"/>
  62. <output message="y:AddResponseMessage"/>
  63. </operation>
  64. <operation name="Subtract">
  65. <input message="y:SubtractMessage"/>
  66. <output message="y:SubtractResponseMessage"/>
  67. </operation>
  68. <operation name="Multiply">
  69. <input message="y:MultiplyMessage"/>
  70. <output message="y:MultiplyResponseMessage"/>
  71. </operation>
  72. <operation name="Divide">
  73. <input message="y:DivideMessage"/>
  74. <output message="y:DivideResponseMessage"/>
  75. </operation>
  76. </portType>
  77. <binding name="MathSoapHttpBinding" type="y:MathInterface">
  78. <soap:binding style="document"
  79. transport="http://schemas.xmlsoap.org/soap/http"/>
  80. <operation name="Add">
  81. <soap:operation soapAction="http://example.org/math/#Add"/>
  82. <input>
  83. <soap:body use="literal"/>
  84. </input>
  85. <output>
  86. <soap:body use="literal"/>
  87. </output>
  88. </operation>
  89. <operation name="Subtract">
  90. <soap:operation soapAction="http://example.org/math/#Subtract"/>
  91. <input>
  92. <soap:body use="literal"/>
  93. </input>
  94. <output>
  95. <soap:body use="literal"/>
  96. </output>
  97. </operation>
  98. <operation name="Multiply">
  99. <soap:operation soapAction="http://example.org/math/#Multiply"/>
  100. <input>
  101. <soap:body use="literal"/>
  102. </input>
  103. <output>
  104. <soap:body use="literal"/>
  105. </output>
  106. </operation>
  107. <operation name="Divide">
  108. <soap:operation soapAction="http://example.org/math/#Divide"/>
  109. <input>
  110. <soap:body use="literal"/>
  111. </input>
  112. <output>
  113. <soap:body use="literal"/>
  114. </output>
  115. </operation>
  116. </binding>
  117. <service name="MathService">
  118. <port name="MathEndpoint" binding="y:MathSoapHttpBinding">
  119. <soap:address location="http://localhost/math/math.asmx"/>
  120. </port>
  121. </service>
  122. </definitions>
End of Code Snippet




References
http://msdn.microsoft.com/en-us/library/ms996486.aspx



TODO: Add more info on WSDL 2.0

No comments: