Web services aren't a single technology or platform; in fact, they are a mixture of several protocols, languages, and formats. And although several different platforms have incorporated web services into their current offerings, there are still some basic parts that remain consistent.
SOAP is a combination of an XML-based language and any number of common protocols for transmitting this data. The SOAP specification describes an intricate language with numerous elements and attributes, intended to describe most types of data. This information can be transported over any number of protocols, but is most commonly sent over HTTP along with other web traffic.
Originally an acronym for Simple Object Access Protocol, the specification now simply goes by SOAP.
There are two main ways of using SOAP, the remote procedure call (RPC) style and the document style.
The RPC style of SOAP treats the web service as though it were an object containing one or more methods (in much the same way you would use a local class to establish communication with a database). A request is made to the service detailing the method name to call and the parameters, if any, to pass. The method is executed on the server, and an XML response is dispatched containing the return value, if any, or an error message if something went awry. Imagine a web service that provides simple arithmetic operations: addition, subtraction, multiplication, and division. Each method takes two numbers and returns a result. An RPC-style request for the add operation would look something like this:
<?xml version="1.0" encoding=" utf-8" ?> <soap:Envelope xmlns:soap=" http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle=" http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body> <w:add xmlns:w=" http://www.wrox.com/services/math"> <w:op1>4.5</w:op1> <w:op2>5.4</w:op2> </w:add> </soap:Body> </soap:Envelope>
Whenever you are dealing with non-trivial XML documents, for example documents that are to be shared across businesses and applications, namespaces come into play. Namespaces are especially important in SOAP because these documents need to be produced and read by different systems. The SOAP namespace, specified in this example as http://schemas.xmlsoap.org/soap/envelope/, is for version 1.1, and can vary depending on which version you are using. The version 1.2 namespace is http://www.w3.org/2003/05/soap-envelope.
The <w:add/> element specifies the name of the method to call (add) and contains the other namespace in the example, http://www.wrox.com/services/math. This namespace is specific to the service that is being called and can be defined by the developer. The soap:encodingStyle attribute points to a URI indicating how the data is encoded in the request. There are a variety of other encoding styles available as well, such as the type system employed in XML schemas.
An optional <soap:Header/> element can be used to contain additional information, such as security credentials. If used, this element comes immediately before <soap:Body/>.
If the request to add two numbers executed successfully, the response message would look like this:
<?xml version="1.0" encoding=" utf-8" ?> <soap:Envelope xmlns:soap=" http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle=" http://schemas.xmlsoap.org/soap/encoding/"> <soap:Body> <w:addResponse xmlns:w=" http://www.wrox.com/services/math"> <w:addResult>9.9</w:addResult> </w:addResponse> </soap:Body> </soap:Envelope>
As you can see, the format is similar to the initial request. The standard way of supplying the result is to create an element with the name of the method followed by the word "Response." In this case, the element is <w:addResponse/>, and has the same namespace as the <w:add/> element in the request. The actual result is returned in the <w:addResult/> element. Note that the web service developer can define all these element names.
Were there a problem processing the SOAP request on the server, assuming the request actually reached that far, then a <soap:Fault> element will be returned. For instance, if the first operand in the example had been wrongly entered as a letter instead of the number, you might receive the following:
<?xml version="1.0" encoding=" utf-8" ?> <soap:Envelope xmlns:soap=" http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <soap:Fault> <faultcode>soap:Client</faultcode> <faultstring>Server was unable to read request. Input string was not in a correct format. There is an error in XML document (4, 13). </faultstring> <detail/> </soap:Fault> </soap:Body> </soap:Envelope>
The <soap:Fault> element, of which there can be only one, gives a clue as to the problem encountered. The most telling information is that contained in <faultcode/>. There are a limited number of options for this value, of which the two common ones are soap:Server and soap:Client. A soap:Server fault code could indicate a problem such as the server being unable to connect to a database. In this case, resending the message may well succeed. If soap:Client is specified, it often means that the message is incorrectly formatted and will not succeed without some modification.
A more human-readable error message is stored in the <faultstring/> element, which contains application-specific error details. If a secondary system, such as a database, is the primary cause of a web service error, information pertaining to this error may be returned in an optional <faultactor/> element (not shown in the previous example).
The document style of SOAP relies on XML schemas to designate the format of the request and response. This style seems to be gaining in popularity and some predict that it will eventually all but replace the RPC style. For a lucid explanation of why people are shying away from RPC with SOAP encoding, see http://msdn.microsoft.com/library/en-us/dnsoap/html/argsoape.asp.
A document-style request may not look that different from an RPC-style request. For example, the RPC request example from the previous section could be a valid document-style request by simply removing the soap:encodingStyle attribute. The difference is that an RPC request always follows the same style, with the method name in a containing element around its parameters; the document-style request has no such constraints. Here's an example that is completely different from an RPC request:
<?xml version="1.0" encoding=" utf-8" ?> <soap:Envelope xmlns:soap=" http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <w:add xmlns:w=" http://www.wrox.com/services/math" op1="4.5" op2="5.4" /> </soap:Body> </soap:Envelope>
Note that the highlighted line contains the method name (add) and two operands (op1 and op2) in a single element. This construct is not possible using RPC-style requests. The document style has this flexibility because there is an accompanying XML schema. A web service can use this XML schema to validate the structure of the request; the service is then free to use the information in the request appropriately. Responses follow the same basic rules as requests: they can be very similar to RPC style or completely different, again based on an XML schema.
Web services created using Visual Studio .NET are, by default, in document style (although this can be changed by applying various attributes to the underlying code).
At this point, you might be wondering where the XML schema is kept and how it is made available to both the client and the service. The answer to those questions lies in yet another abbreviation: WSDL.
Web Services Description Language (WSDL) is another XML-based language that was created to describe the usage of a particular web service, or rather, how a particular service could be called. The resulting specification describes an incredibly dense language, designed to be extremely flexible and allow for as much re-use as possible; it is the sort of document that is manually constructed only by the most ardent enthusiast. Typically, a software tool is used for the initial WSDL file creation and then hand tweaked, as necessary.
The following is a WSDL file describing a sample math service with a single add method (which you will be building later):
<?xml version="1.0" encoding=" utf-8"?> <wsdl:definitions xmlns:http=" http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap=" http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s=" http://www.w3.org/2001/XMLSchema" xmlns:tns=" http://www.wrox.com/services/math" xmlns:wsdl=" http://schemas.xmlsoap.org/wsdl/" targetNamespace=" http://www.wrox.com/services/math"> <wsdl:types> <s:schema elementFormDefault="qualified" targetNamespace=" http://www.wrox.com/services/math"> <s:element name=" add"> <s:complexType> <s:sequence> <s:element minOccurs="1" maxOccurs="1" name=" op1" type=" s:float" /> <s:element minOccurs="1" maxOccurs="1" name=" op2" type=" s:float" /> </s:sequence> </s:complexType> </s:element> <s:element name=" addResponse"> <s:complexType> <s:sequence> <s:element minOccurs="1" maxOccurs="1" name=" addResult" type=" s:float" /> </s:sequence> </s:complexType> </s:element> </s:schema> </wsdl:types> <wsdl:message name=" addSoapIn"> <wsdl:part name=" parameters" element=" tns:add" /> </wsdl:message> <wsdl:message name=" addSoapOut"> <wsdl:part name=" parameters" element=" tns:addResponse" /> </wsdl:message> <wsdl:portType name=" MathSoap"> <wsdl:operation name=" add"> <wsdl:documentation> Returns the sum of two floats as a float </wsdl:documentation> <wsdl:input message=" tns:addSoapIn" /> <wsdl:output message=" tns:addSoapOut" /> </wsdl:operation> </wsdl:portType> <wsdl:binding name=" MathSoap" type=" tns:MathSoap"> <soap:binding transport=" http://schemas.xmlsoap.org/soap/http" style=" document" /> <wsdl:operation name=" add"> <soap:operation soapAction=" http://www.wrox.com/services/math/add" style=" document" /> <wsdl:input> <soap:body use=" literal" /> </wsdl:input> <wsdl:output> <soap:body use=" literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name=" Math"> <wsdl:documentation> Contains a number of simple arithmetical functions </wsdl:documentation> <wsdl:port name=" MathSoap" binding=" tns:MathSoap"> <soap:address location=" http://localhost/Math/Math.asmx" /> </wsdl:port> </wsdl:service> </wsdl:definitions>
Remember that this WSDL is describing only a basic service that adds two numbers; for simplicity, the three other methods you will be implementing have been removed. Although this WSDL file is long and complex, you should understand what its various sections mean.
The document element, <wsdl:definitions/>, encompasses the content and allows the declaration of various namespaces. The next element, <wsdl:types/>, contains the XML schema used by the service. Inside of this element is <s:schema/>, which describes the format of all elements that can appear in the <soap:Body/> of either the request or the response.
The first element described in the schema is <add/>. Since the <s:schema/> element has elementFormDefault set to qualified, <add/> is assumed to be in the namespace designated by the targetNamespace attribute, http://www.wrox.com/services/math. The <add/> element is then declared to contain a sequence of two other elements, <op1/> and <op2/>. Both of these elements have minOccurs and maxOccurs set to 1, which means that they must both appear once and once only. They also both have a type attribute of s:float, which is one of the built-in XML schema types.
You can find a complete list of XML schema data types at www.w3.org/TR/xmlschema-0/#CreatDt. If your service needs more complicated types than these, you can construct complex types by aggregating and restricting these base types.
Next in the schema is another <s:element/>, this one describing <addResponse/>. This element is defined to have one child element, <addResult/>, which contains the result of the operation (also defined as type s:float). This is the last entry in the included XML schema.
Back in the main body of the WSDL file is a short section describing two <wsdl:message/> elements: addSoapIn and addSoapOut. Each of these elements has a <wsdl:part/> element that specifies the element in the XML schema to use. These both refer to the two elements add and addResponse, respectively. This section states the format of each message.
The following section, <wsdl:portType/>, is used to group the <wsdl:message> elements into operations. An operation is considered to be a single unit of work and, therefore, comprises of a <wsdl:input> and normally a <wsdl:output> and an optional <wsdl:fault> element. The preceding example has one <wsdl:portType> and describes a <wsdl:operation/> named add. The message attributes on its <wsdl:input> and <wsdl:output> children refer back to the <wsdl:message> elements previously defined. There is also a <wsdl:documentation/> element containing a user-friendly description of the method. (You will learn where this information comes from later in the chapter.)
After the port type is a <wsdl:binding/> block. A binding pairs an operation with a protocol used to communicate with the service. There are three bindings described in the WSDL specification, SOAP, HTTP GET/POST, and MIME.
This chapter concentrates on the SOAP binding. The HTTP GET/POST binding deals with how URLs are constructed (for GET requests) or how the form data is encoded (for POST requests). The MIME binding allows parts of the message, normally the output, to be expressed in different mime types. This means that one part of the response could be in XML, whereas a second part could be in HTML.
You can read more about these alternative bindings at www.w3.org/TR/2002/WD-wsdl12-bindings-20020709/.
First, the name of the binding is set to MathSoap, and the type points to the MathSoap port type defined in the <wsdl:portType> section. Second, the <soap:binding/> element uses the transport attribute to specify that the service operates over HTTP. The <wsdl:operation/> element simply defines the name of the method, add. The <soap:operation/> element contains the soapAction that needs to be incorporated into the header of the HTTP request as well as the style attribute, which specifies that the SOAP message will be a document type rather than an RPC type.
The main difference between a document-style message and an RPC-style message is that the document style sends the message as elements within the <soap:body> that can have whatever structure the sender and receiver agree on using the embedded schema as a guide. An RPC-style message, however, has an element named after the method being called. This in turn will have one element for each parameter the method accepts.
The <soap:operation/> element has two children, <wsdl:input> and <wsdl:output>, which are used to further describe the request and response format. In this case, the <soap:body> specifies a use attribute of literal. In practical terms, this is the only option with document-style services; with RPC-style services the choice extends to encoded, in which case the <soap:body> would further specify exactly which encoding type was to be used for the parameter types.
The final part of the document, <wsdl:service/>, deals with how to call the service from a client. It also contains a human-readable description of the service and the <wsdl:port/> element, which references the MathSoap binding in the last document section. Perhaps the most important element in this section is <soap:address/>, which contains the crucial location attribute containing the URL needed to access the service.
<wsdl:service name=" Math"> <wsdl:documentation> Contains a number of simple arithmetical functions </wsdl:documentation> <wsdl:port name=" MathSoap" binding=" tns:MathSoap"> <soap:address location=" http://localhost/Math/Math.asmx" /> </wsdl:port> </wsdl:service>
Looking at a complete WSDL file may be a bit daunting for new developers, but the good news is that you will probably never have to hand code one yourself. In fact, the example file in this section was created automatically by the .NET web service, which examines the underlying code and generates the necessary XML.
XML schemas are a vast topic and a full discussion is outside the scope of this book. If you'd like to learn more about XML schemas, consider picking up Beginning XML, 3rd Edition (Wiley Publishing, ISBN 0-7645-7077-3), or for a web tutorial, visit www.w3schools.com/schema/default.asp.
Representational State Transfer, often abbreviated as REST, describes a way of using the existing HTTP protocol to transmit data. Although used mostly for web services, REST can be used for any type of HTTP-based request and response systems as well. In regard to web services, REST enables you to call a given URL in a specific format to return data (which will also be in a specific format). This data may contain further information on how to retrieve even more data. For the web service usage, the data will be returned as XML.
For example, suppose Wrox would like to provide a way for others to retrieve a list of all authors. REST-style web services use simple URLs to access data; the Wrox Book service could use this URL to retrieve the list of authors:
This service may return an XML representation of the known authors along with information on how to access details about each one, such as:
<?xml version="1.0" encoding=" utf-8" ?> <authors xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.wrox.com/services/authors-books" xlink:href="http://www.wrox.com/services/authors/"> <author forenames="Michael" surname="Kay" xlink:href="http://www.wrox.com/services/authors/kaym" id=" kaym"/> <author forenames="Joe" surname=" Fawcett" xlink:href="http://www.wrox.com/services/authors/fawcettj" id=" fawcettj"/> <author forenames="Jeremy" surname=" McPeak" xlink:href="http://www.wrox.com/services/authors/mcpeakj" id=" mcpeakj"/> <author forename=" Nicholas" surname=" Zakas" xlink:href="http://www.wrox.com/services/authors/zakasn" id=" zakasn"/> <!-- More authors --> </authors>
There are a couple of things to note about this XML. First, a default namespace of http://www.wrox.com/services/authors-books is declared so that any un-prefixed elements, such as <authors/>, are assumed to belong to this namespace. This means that the <authors/> element can be differentiated from another element with a similar name but from a different namespace. The namespace URI, http://www.wrox.com/services/authors-books, is used simply as a unique string; there is no guarantee that an actual resource is available at that location. The key is that it is a Uniform Resource Identifier (URI), which is simply an identifier, not a Uniform Resource Locator (URL), which would indicate that a resource is available at a specific location.
Second, note the use of the href attribute from the http://www.w3.org/1999/xlink namespace. Although not essential, many REST-style services have now standardized on this notation for what, in HTML, would be a standard hyperlink.
XLink is a way of linking documents that goes way beyond the straightforward hyperlinks of HTML. It provides capabilities to specify a two-way dependency so that documents can be accessible from each other as well as indicating how a link should be activated — for example, by hand, automatically, or after a preset time. Its cousin, XPointer, is concerned with specifying sections within a document and arose from the need for a more powerful notation than the simple named links within HTML pages.
Although they have both reached recommendation status at the W3C, they are still not widely used. For more information, visit www.w3.org/XML/Linking.
If used in a web site or web application, the XML returned from the REST service would be transformed, either client-side or server-side, to a more user-friendly format (most likely HTML) — perhaps something like this:
<html> <head> <title>Wrox Authors</title> </head> <body> <a href="http://www.wrox.com/services/authors/kaym">Michael Kay</a> <a href="http://www.wrox.com/services/authors/fawcettj">Joe Fawcett</a> <a href="http://www.wrox.com/services/authors/mcpeakj">Jeremy McPeak</a> <a href="http://www.wrox.com/services/authors/zakasn">Nicholas Zakas</a> </body> </html>
The user could then retrieve individual author data by following one of the links, which may return XML similar to this:
<?xml version="1.0" encoding=" utf-8" ?> <author xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.wrox.com/services/authors-books" xlink:href="http://www.wrox.com/services/authors/fawcettj" id=" fawcettj" forenames=" Joe" surname=" Fawcett"> <books> <book xlink:href="http://www.wrox.com/services/books/0764570773" isbn="0764570773" title=" Beginning XML"/> <book xlink:href="http://www.wrox.com/services/books/0471777781" isbn="0471777781" title=" Professional Ajax"/> </books> </author>
Again, you see that the elements are in the http://www.wrox.com/services/authors-books namespace and the xlink:href attribute is a way to extract further information. An HTML representation of this data may look like this:
<html> <head> <title>Author Details</title> </head> <body> <p>Details for <a href="http://www.wrox.com/services/authors/fawcettj">Joe Fawcett</a></p> <p>Books</p> <a href="http://www.wrox.com/services/books/0764570773">Beginning XML</a> <a href="http://www.wrox.com/services/books/0471777781">Professional Ajax</a> </body> </html>
And if, per chance, the user feels like following the link for Professional Ajax, he or she may receive the following XML in response:
REST-style services are fairly straightforward and follow a repeating pattern. For example, you may get a complete list of authors by using http://www.wrox.com/services/authors/, whereas a slight modification, adding an author ID at the end, may retrieve information about a single author, perhaps from http://www.wrox.com/services/authors/fawcettj.
The service can be implemented in any number of ways. It could be through static web pages or, more likely, some sort of server-side processing such as ASP, JSP, or PHP, that fetch data from a database and return the appropriately constructed XML. In this case the URL would be mapped by the server into an application-specific way of retrieving the data, possibly by invoking a stored procedure on the database in question.
You can read more about REST-style services (also called RESTful services) at www.network.world.com/ee/2003/eerest.html.