XML Files

The Birth of Web Services

Aaron Skonnard

Contents

Distributed Computing Technology
Demand for Interoperability
Web Applications
An XML Revolution
Wire Contract = Interface
XML 1.0 and Namespaces
XML Schema
Framing XML Messages
SOAP
WSDL
UDDI
Definition Revisited
The Future

The XML technology receiving the most attention these days is Web Services. Web Services is a term commonly used to describe an entire new breed of applications. Unfortunately, not everyone agrees on what that breed is. Often, the term Web Services is used to generate hype rather than to describe real technological advances. To help bring these concepts into focus, in this column I will review some pertinent background information, then concentrate on the core Web Services platform and its fundamental characteristics.

So, what is a Web Service? Does it require any particular transport like HTTP or SMTP? If so, can you use others, like MSMQ? Does it mandate the use of XML and SOAP or can other content types such as MIME, JPG, MP3, or URL-encoded data in a query string be used as well? Does it rely on standard description languages like XML Schema and Web Services Description Language (WSDL)? As you can see, questions abound. A workable definition would have to be as general as possible. Here's the reductionist definition: a Web Service is an application component accessible over open protocols (see Figure 1).

Figure 1 Web Services Definition

Figure 1** Web Services Definition **

I hate this definition. It says nothing about the characteristics of a Web Service. Although this definition might be perfect for Webster's, it doesn't help developers understand and use the technology. As it turns out, agreeing on a specific, concrete definition is vitally important if developers are actually going to achieve interoperability—the ultimate goal of Web Services.

Web Services represents a new platform on which developers can build the same distributed applications they've always built, but this time with interoperability as the highest priority.

Distributed Computing Technology

The Web Services platform also represents the evolution of past distributed component technologies like remote procedure calls (RPC), ORPC (DCOM, Corba, Java RMI), messaging (MSMQ, MQSeries), and even modern Web applications (like Google.com). Because RPC was so difficult, developers layered object facades over the RPC mechanism to hide complexity. This led to the many flavors of object-oriented remote procedure calls (ORPC). Of course, not all application communication can be modeled with RPC, so other messaging paradigms (like those provided by MSMQ) were necessary. Then, over the years, as developers struggled with interoperability between the various ORPC and messaging systems, they turned to the evolving Web as a potential solution for these challenges.

DCOM failed to become a ubiquitous platform for building distributed applications, as did Corba and Java RMI, because they were too complex and attempted to do too much. Instead of focusing on a minimalist platform for communicating between systems, most ORPC implementations attempted to do everything under the sun. Ultimately, they required a sophisticated runtime to be installed on all participating machines to make the underlying mechanisms completely transparent.

In ORPC, the objects on both sides communicate over a transport protocol (such as TCP/UDP) using a specific message format. Efficient binary formats (like NDR) are used to increase performance and flexibility. Higher-level interface description languages (IDL, for example) are used to shield developers from the complexities of the wire-level message. Also, where the object actually resides can be discovered by clients at run time (via the registry in DCOM). Because the description language describes exactly what the message should be once on the wire and its location can be discovered, IDL compilers can generate proxy/stub code to automate the process and provide complete transparency to the developer.

In addition to these basic facets of object communication, most ORPC systems also provide additional application-level services such as security, garbage collection, session management, distributed transactions, and so forth, all of which require complex communication patterns of their own.

Figure 2 DCOM Example

Figure 2** DCOM Example **

Figure 2 illustrates the basic facets of object communication and the specific techniques employed by DCOM. All ORPC implementations provide the functionality described here. Unfortunately, they all do it differently. Figure 3 describes how the major ORPC implementations differ in these areas. Notice that there is absolutely nothing standard about the various implementation techniques, not to mention the more severe differences that you'd encounter in the various higher-level application services. This obviously doesn't bode well for interoperability.

Figure 3 Comparing ORPC Implementations

  DCOM CORBA Java RMI
RPC Protocol RPC IIOP IIOP or JRMP
Message Format NDR CDR Java Ser. Format
Description IDL OMG IDL Java
Discovery Windows Registry Naming Service RMI Registry or JNDI

Demand for Interoperability

Interoperability has always been a major concern for organi-zations, but over the past decade it has become a much bigger priority across the industry. There are two main areas where interoperability is a significant challenge: Enterprise Application Integration (EAI) and Business-to-Business Integration (B2Bi).

EAI represents the challenge most enterprises face in integrating their various applications with each other. For example, consider an enterprise that has a Windows® 95 LAN, a Windows 2000 Web server running ASP.NET, an AS-400 accounting and payroll system, and several Unix-based MRP and SAP systems. These various systems surely need to communicate and exchange information to serve the needs of the enterprise. It's always been a challenge to make this happen effectively, so much of a challenge that many organizations actually rely on printers and fax machines as part of their overall integration strategy.

B2Bi represents the business interactions between different enterprises. If one business wants to purchase supplies from another, they have to interact and exchange information—and they rarely happen to be using the same technology suites. Many organizations want to extend their reach to users. But users don't like being shoehorned into any particular platform or technology suite, so interoperability becomes an even bigger challenge than ever before.

Once Web servers and Web browsers became available for all major platforms, interoperability finally became a reality. Windows clients began accessing applications running on Unix servers. Macintosh clients began exchanging information with mainframes. And clients on Linux machines began communicating with servers running Windows.

The Web became a quick fix for the bigger interoperability issues. Many developers began writing ASP pages like this:

<% set o = Server.CreateObject("MyLib.MyBusinessObject") o.DoSomeWork Request("arg1"), CDbl(Request("arg2") %>

This ASP page simply makes a COM business object (MyLib.MyBusinessObject) available over HTTP. Using this minimalist approach instead of DCOM, simplifies integration since any client with access to HTTP can invoke DoSomeWork. Using DCOM on the wire requires clients to have the DCOM infrastructure installed before they can invoke the same operation.

Web Applications

The emergence of Web applications, a new type of distributed application built around Web browsers, was inevitable. Take a look at the one shown in Figure 4—an online mortgage calculator. The user interacting with this Web application supplies the necessary values, presses Calculate Payment, and the page is refreshed with the calculated payments displayed below. When the user invokes the operation, the input data is sent via an HTTP POST in the URL-encoded data shown in this partial:

txtYears=30&txtInterest=8.0&txtAmount=100000 &txtTax=1000&txtInsurance=300

The HTTP response contains a new HTML page with the calculated values embedded within.

Figure 4 Mortgage Calculator

Figure 4** Mortgage Calculator **

Because a human is a required part of the system, this might be a key reason Web applications aren't usable as a distributed application component. In addition, URL-encoding and HTML aren't flexible, powerful, or descriptive enough for most data representation needs.

An XML Revolution

Around the same time that dot-com became a household word, XML began gaining traction throughout the industry as a widely accepted data representation format. In fact, it wasn't long after XML 1.0 became a W3C Recommendation in 1998 that XML parsers became available for just about every commercially viable platform and programming language around. Within a short time, the industry began focusing on additional layered services like DOM, XPath, XSLT, XML Schema, SOAP, WSDL, and Universal Description, Discovery, and Integration (UDDI). Developers quickly realized that the entire suite of technologies offered a robust solution to the deficiencies of Web applications.

With their eyes set on interoperability, many joined in what might be described as an XML-based revolution of distributed application development, combining the positive aspects of Web application design with the key benefits offered by new XML technologies. In order for this emerging Web Services platform to overcome the deficiencies of its predecessors, it would have to be built on standard, widely supported protocols and languages, yet have the power of past distributed systems. Specifically, the Web Services platform would have to provide the following features:

  • Standard communication protocols
  • A standard data representation format
  • Standard description languages
  • A standard discovery mechanism

Wire Contract = Interface

One characteristic that distinguishes the Web Services platform from earlier ORPC systems is that the wire-level contract is the true interface to the system. Most ORPC systems took it upon themselves to hide all of the wire-level details from the developer. Developers simply described their interfaces in IDL (or something like it) and a compiler generated the code to deal with what went across the wire. This worked fine as long as both systems used the same ORPC infrastructure, but in a world where interoperability is the central goal, this approach just doesn't work.

Developers must embrace what goes on the wire to have a fighting chance at solving interoperability issues when they occur. With Web Services, the wire-level contract is the first-class citizen, the central rendezvous point for communicating applications. The wire-level contract is defined in terms of various XML technologies, each of which plays an important role in the platform.

Figure 5 Web Services Platform

Figure 5** Web Services Platform **

There are several XML technologies that help represent, describe, and discover the wire contract for Web Services. These include XML 1.0 + Namespaces, SOAP, XML Schema, WSDL, and UDDI as illustrated in Figure 5.

XML 1.0 and Namespaces

XML 1.0+ Namespaces provides the syntax for data representation. XML 1.0 is to Web Services what NDR is to DCOM. Using XML 1.0, developers can easily represent data from their internal systems in a portable format. This simplifies things for developers on the other end of the wire since all they need to process the message is an XML parser.

For example, the mortgage calculator's requested information can be represented using the following XML 1.0 document:

<m:CalculateMortgage xmlns:m="https://example.org/mortgage"> <amount>100000</amount> <years>30</years> <interest>8.0</interest> <annualTax>1000</annualTax> <annualInsurance>300</annualInsurance> </m:CalculateMortgage>

Notice that the document contains a CalculateMortgage element representing the operation, and several child elements containing the required input: amount (for the principal), years (for the term), interest, annualTax, and annualInsurance. The response message can also be represented in an XML document, as shown in this example:

<m:CalculateMortgageResponse xmlns:m="https://example.org/mortgage"> <MortgagePayments> <MonthlyPI>733.76</MonthlyPI> <MonthlyTax>83.33</MonthlyTax> <MonthlyInsurance>25</MonthlyInsurance> <MonthlyTotal>842.09</MonthlyTotal> </MortgagePayments> </m:CalculateMortgageResponse>

In this case, the CalculateMortgageResponse element contains another structure named MortgagePayments, which contains the calculated payments.

Using XML 1.0 to represent the interface makes it much easier for other programs to consume the operation. XML 1.0 is easy to program through a variety of services layered over the XML 1.0 abstract data model, otherwise known as the Infoset. These services include XPath for querying documents, XSLT for transforming documents, and SAX, DOM, XmlReader and XmlWriter, XPathNavigator, and other APIs for programmatically working with documents. These technologies make it trivial to work with the request/response documents just shown.

This code snippet illustrates how to extract the input data using the XML streaming API in the Microsoft® .NET Framework:

void processInputStream(Stream s) { double amount, years, interest, annualTax, annualIns; XmlReader r = new XmlTextReader(s); r.ReadStartElement("CalculateMortgage", "https://example.org/mortgage"); amount = XmlConvert.ToDouble(r.ReadElementString("amount")); years = XmlConvert.ToDouble(r.ReadElementString("years")); ••• r.ReadEndElement(); // CalculateMortgage ••• }

Developers who want to use the DOM API can use the .NET XmlDocument class along with XPath expressions, as shown here:

void processInputStream(Stream s) { double amount, years, interest, annualTax, annualIns; XmlDocument doc = new XmlDocument(); doc.Load(s); XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); nsmgr.AddNamespace("x", "https://example.org/mortgage"); amount = XmlConvert.ToDouble(doc.selectSingleNode( "/x:CalculateMortgage/amount", nsmgr).InnerText); ••• }

Generating the XML response message is just as easy through the .NET XmlWriter class, as you can see in Figure 6.

Figure 6 Generating a Response with XMLWriter

void generateOutputStream(Stream s, string pi, string tax, string ins, string total) { XmlWriter w = new XmlTextWriter(s); w.WriteStartDocument(); w.WriteStartElement("m", "CalculateMortgageResponse", "https://example.org/mortgage"); w.WriteStartElement("MortgagePayments"); w.WriteElementString("MonthlyPI", pi); w.WriteElementString("MonthlyTax", tax); w.WriteElementString("MonthlyInsurance", ins); w.WriteElementString("MonthlyTotal", total); w.WriteEndElement(); // MortgagePayments w.WriteEndElement(); // CalculateMortgageResponse w.Close(); }

With XML processing code in place, you can finally break free from the bonds of the browser and integrate the Mortgage Calculator component with other applications. Figure 7 shows a .NET Windows Forms application that works by going directly against the XML message interface.

Figure 7 Windows Forms App

Figure 7** Windows Forms App **

Notice that XML 1.0 treats all information as text. If the code expects a particular type for each field, it must explicitly perform coercion. In this case, the code coerces the extracted strings to doubles. The code also expects a specific structure and order of elements. If a stream comes in with the elements in a slightly different order, an exception will be thrown.

Others have to be familiar with these details (the expected type and structure) in order to produce documents that can be processed by this code. Such details can be described in human-readable documentation like HTML pages or Word docs, but if it's also described in a machine-readable format, much of the XML processing could be automated through programming.

XML Schema

XML Schema makes it possible to describe the type and structure of XML documents. An XML Schema definition serves as the official documentation for a set of XML messages. Since XML Schema is an XML vocabulary itself, it's easy to process schema definitions programmatically using the techniques illustrated in the previous section. The code listed in Figure 8 contains an XML Schema definition that describes the CalculateMortgage request/response messages.

Figure 8 Mortgage Calculator Schema

<s:schema elementFormDefault="qualified" targetNamespace="https://example.org/mortgage" xmlns:s="https://www.w3.org/2001/XMLSchema" xmlns:tns="https://example.org/mortgage" > <s:element name="CalculateMortgage"> <s:complexType> <s:sequence> <s:element name="amount" type="s:double" /> <s:element name="years" type="s:double" /> <s:element name="interest" type="s:double" /> <s:element name="annualTax" type="s:double" /> <s:element name="annualInsurance" type="s:double" /> </s:sequence> </s:complexType> </s:element> <s:element name="CalculateMortgageResponse"> <s:complexType> <s:sequence> <s:element name="MortgagePayments" type="tns:MortgagePayments" /> </s:sequence> </s:complexType> </s:element> <s:complexType name="MortgagePayments"> <s:sequence> <s:element name="MonthlyPI" type="s:double" /> <s:element name="MonthlyTax" type="s:double" /> <s:element name="MonthlyInsurance" type="s:double" /> <s:element name="MonthlyTotal" type="s:double" /> </s:sequence> </s:complexType> </s:schema>

As you can see, XML Schema allows you to describe the exact structure of elements with the same expressiveness as Document Type Definitions (DTDs) plus a bit more. In addition, it allows developers to annotate text-only elements and attributes with simple types (int, double, boolean, and so on). An XML Schema simple type describes a value space and the corresponding lexical space. This additional type information can be used by schema processors to perform important value-space validation in addition to structural validation.

.NET makes validation possible through XmlValidatingReader, which you wrap around an underlying XmlTextReader. It performs the validation as you read through the stream of nodes:

void processInputStream(Stream s) { XmlReader r = new XmlTextReader(s); XmlValidatingReader vr = new XmlValidatingReader(r); vr.Schemas.Add("https://example.org/mortgage", "mortgagecalculator.xsd"); XmlDocument doc = new XmlDocument(); doc.Load(vr); // once loaded, we know it's valid ... // continue processing with XPath }

XML Schema type information also facilitates code generation that can greatly simplify XML processing code. If a mapping can be established between the XML Schema type system and another type system, like the common language runtime (CLR), moving between XML instances and CLR objects should be free (see Figure 9). This essentially means that the XmlReader/XmlWriter code shown earlier could be generated directly from the schema definition.

Figure 9 Mapping XML to Objects

Figure 9** Mapping XML to Objects **

.NET provides a command-line utility called xsd.exe for mapping between the two type systems. If you provide xsd.exe with a schema definition and the /c switch, it produces a set of C# classes that map to the original schema types (use /l:VB to produce Visual Basic® .NET classes):

xsd.exe /c mortgagecalc.xsd

The generated classes can then be used to process/generate the XML messages described in the schema. The XmlSerializer class (see System.Xml.Serialization) performs the mapping between .NET objects and XML instance files at run time. Notice in the following example, there isn't a line of XmlReader or DOM code; it's all taken care of by XmlSerializer:

void processInputStream(Stream s) { XmlSerializer xs; xs = new XmlSerializer(typeof(CalculateMortgage)); // CalculateMortgage generated by xsd.exe /c CalculateMortgage cm = (CalculateMortgage)xs.Deserialize(s); // access fields here, cm.amount, cm.years, ... ••• }

XML Schema is a big win for the Web Services platform where bridging between type systems is a given. As developers build Web Services using XML Schema, however, the next challenge they will face will have to do with extensibility.

For example, if you wanted to include the CalculateMortgage operation within a logical transaction, where would you put the transaction ID? Or what if you wanted to include special security tokens with the request, or you wanted to influence routing with some extra information? Adding such information into the message requires updating the schema either by modifying the original type definitions, or by defining new extended types that add the new information. This approach would be tedious, inflexible, and hard to maintain over time.

Many would argue that such information doesn't belong in the message anyway. In the examples I gave, the extra information isn't required to perform the operation. However, the information does influence how the operation is performed, allowing the client and server to negotiate different processing models. This information probably doesn't belong in the message itself, but in a separate location designed for extensible headers.

Framing XML Messages

Certain network communications protocols, such as HTTP and SMTP, are extensible through the use of headers. In the case of HTTP, the headers come after the command line and continue until the blank line above the body:

POST /somevroot/something.ashx HTTP/1.1 Content-Type: text/xml Content-Length: 324 Host: www.develop.com <s:Envelope ...

If Web Services were only going to be used over HTTP, you could rely on HTTP's extensibility mechanism and define new headers for what you need. But if they are going to be used over multiple protocols (see Figure 10), you need a more generic solution that isn't tied to a specific network protocol. What's needed is a solution that embeds the headers within the XML message itself.

Figure 10 Intermediaries

Figure 10** Intermediaries **

SOAP

SOAP provides an extensible framing mechanism for XML messages. SOAP is similar to the HTTP protocol in that there is a clear distinction between the headers and body (payload), as follows:

<soap:Envelope xmlns:soap="..."> <soap:Header> <!-- extensible headers --> </soap:Header> <soap:Body> <!-- payload --> </soap:Body> </soap:Envelope>

In addition to framing and extensibility, SOAP also defines a standard representation for errors and a standard binding to HTTP (POST, Content-Type: text/xml, SOAPAction, and so on) and RPC. The code in Figure 11 shows a SOAP request and response for the CalculateMortgage operation.

Figure 11 CalculateMortgage

SOAP Request

POST /mortgagecalc/mc.asmx HTTP/1.1 Host: example.org Content-Type: text/xml; charset=utf-8 Content-Length: 323 SOAPAction: "https://example.org/mortgage/CalculateMortgage" <soap:Envelope xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <x:Credentials xmlns:x="https://example.org/security"> <username>billy</username> <password>yllib</password> </x:Credentials> </soap:Header> <soap:Body> <m:CalculateMortgage xmlns:m="https://example.org/mortgage"> <amount>100000</amount> <years>30</years> <interest>8.0</interest> <annualTax>1000</annualTax> <annualInsurance>300</annualInsurance> </m:CalculateMortgage> </soap:Body> </soap:Envelope>

SOAP Response

HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 374 <soap:Envelope xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <m:CalculateMortgageResponse xmlns:m="https://example.org/mortgage"> <MortgagePayments> <MonthlyPI>733.76</MonthlyPI> <MonthlyTax>83.33</MonthlyTax> <MonthlyInsurance>25</MonthlyInsurance> <MonthlyTotal>842.09</MonthlyTotal> </MortgagePayments> </m:CalculateMortgageResponse> </soap:Body> </soap:Envelope>

Since there aren't any standard SOAP headers yet, SOAP doesn't provide much functionality beyond the simple extensibility mechanism. The value of SOAP will increase over time as organizations work together to define standard headers. One way Microsoft is currently participating is by pursuing the Global XML Web Services Architecture (GXA) effort.

In order to invoke a SOAP operation, you need several pieces of information besides the XML Schema that describes the messages. For example, you need to know the endpoint location (such as a URL), the supported protocols and encoding techniques (HTTP, MIME, SOAP section 5 encoding rules, literal XML Schema definitions, and so forth), the value to put in the SOAPAction header (if any), what other headers are required/supported, how to correlate response messages with request messages, and more.

If you were writing the code to invoke the SOAP service manually, you would supply such information explicitly. But to generate Web Service classes (proxies and stubs) that automate the invocation, this information must also be described somewhere.

WSDL

WSDL makes it possible to describe an endpoint and its behavior. WSDL is to Web Services what IDL is to DCOM. WSDL layers additional information over the XML Schema definitions that describe the actual messages. This extra information makes it possible for toolkits to automatically generate proxy and stub classes that know how to invoke Web Service operations without developer intervention.

Figure 12 contains a WSDL document describing the Mortgage Calculator Web Service I've been working with thus far.

Figure 12 Mortgage Calculator WSDL Document

<definitions xmlns="https://schemas.xmlsoap.org/wsdl/" xmlns:soap="https://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="https://example.org/mortgage-tools" targetNamespace="https://example.org/mortgage" > <!-- import schema definition --> <import href="https://mortgagecalculator.xsd" namespace="https://example.org/mortgage"/> <message name="CalculateMortgageSoapIn"> <part name="parameters" element="tns:CalculateMortgage"/> </message> <message name="CalculateMortgageSoapOut"> <part name="parameters" element="tns:CalculateMortgageResponse"/> </message> <portType name="MortgageCalculatorSoap"> <operation name="CalculateMortgage"> <input message="tns:CalculateMortgageSoapIn"/> <output message="tns:CalculateMortgageSoapOut"/> </operation> </portType> <binding name="MortgageCalculatorSoap" type="tns:MortgageCalculatorSoap"> <soap:binding style="document" transport="https://schemas.xmlsoap.org/soap/http"/> <operation name="CalculateMortgage"> <soap:operation style="document" soapAction= "https://example.org/mortgage/CalculateMortgage" /> <input> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding> <service name="MortgageCalculator"> <port name="MortgageCalculatorSoap" binding="tns:MortgageCalculatorSoap"> <soap:address location= "https://example.org/mortgagecalc/mc.asmx"/> </port> </service> </definitions>

Notice that all information required to invoke the CalculateMortgage operation is contained in the description. The .NET Framework provides a utility called wsdl.exe that generates Web Service proxy/stub classes from WSDL files (it is also available from the Add Web Reference dialog in Visual Studio® .NET).

If you use the wsdl.exe /server, you'll get a server-side ASP.NET class that implements the Web Service operation according to the details in the WSDL file. ASP.NET makes it easy to get Web Services up and running by simply annotating public methods with [WebMethod]:

[WebMethod] public MortgagePayments CalculateMortgage( string amount, string years, string interest, string annIns, string annTax) { MortgagePayments p = new MortgagePayments(); ... // calculate mortgage payments here; return p; }

If you don't use the /server switch, you'll get a Web Service proxy class. Once you have the proxy, it's trivial to invoke the operation, as you can see from Figure 13.

Figure 13 Invoke the Calculator

void InvokeCalculateMortgage(string amount, string years, string interest, string annIns, string annTax) { try { MortgageCalculator mc = new MortgageCalculator(); MortgagePayments payments = ms.CalculateMortgage( amount, years, interest, annIns, annTax); ... // process successful result here } catch(Exception e) { // process SOAP fault here } }

The generated class, MortgageCalculator, looks like any .NET class with a method called CalculateMortgage. And notice that if the server generates a SOAP Fault, it's automatically mapped back to a .NET exception.

By default, the WSDL-generated proxy has a hardcoded endpoint location. You can configure it to read the endpoint location from a local configuration file, but that's still not quite as flexible as some would like. Once a Web Service is implemented, described, and deployed, it would be really very helpful if it were easy for other developers to find and use it.

UDDI

UDDI is an industry-wide initiative to standardize how Web Services are discovered. UDDI defines a SOAP-based API for querying centralized Web Service repositories. UDDI makes it possible for developers to discover the technical details of a Web Service (WSDL) as well as other business-oriented information and classifications. For example, using UDDI you should be able to query for all Web Services related to stock quote information, implemented over HTTP, and that are free of charge.

UDDI is to Web Services what the registry is to DCOM. UDDI simply makes it possible to build an extra level of indirection into your Web Service code so you don't have to hardcode endpoint locations at development time. This approach works fine within controlled environments (like a LAN or supply chain).

You'll also hear people try to make UDDI into more than it really is, pumping the idea of truly dynamic runtime discovery. This didn't work well in COM with component categories and I doubt it will work any better with Web Services. No developer or organization I know is going to let a piece of code choose their business partners dynamically. There are just too many quality control and legal issues that get in the way.

UDDI is, however, a useful tool for developers when they need dynamic discovery in their enterprise or when they need to identify potential business partners on the Web at development time.

Definition Revisited

Together, the XML technologies I've discussed here offer a complete platform for distributed application development that facilitates interoperability. So a more precise definition for the term Web Service might be an application component that:

  • Communicates via open protocols (HTTP, SMTP, etc.)
  • Processes XML messages framed using SOAP
  • Describes its messages using XML Schema
  • Provides an endpoint description using WSDL
  • Can be discovered using UDDI

This definition concurs with the Web Services Interoperability Organization's (WS-I), description of the Web Services basic profile (see https://www.ws-i.org). One reason the WS-I was created was to help the industry focus in on a Web Services definition that will ultimately lead to better interoperability.

If you take Figure 3 and add a column for the Web Services platform, you'll see every technology is based on open protocols and languages (see Figure 14). And if you redraw Figure 2, which illustrates how DCOM works, you'll see there is a replacement for every major piece of the DCOM plumbing (see Figure 15).

Figure 14 Comparing Web Services

  DCOM CORBA Web Services
RPC Protocol RPC IIOP HTTP + SOAP
Message Format NDR CDR XML 1.0
Description IDL OMG IDL WSDL + XSD
Discovery Windows Registry Naming Service UDDI

Figure 15 Web Services RPC Example

Figure 15** Web Services RPC Example **

The Future

The Web Services platform defines a simple, interoperable, messaging framework on which you can build more sophisticated plumbing. It doesn't provide the same services as DCOM. Many of the important features of a distributed system aren't available yet (like security, routing, transactions, and so on). These pieces will be rolled out over time through standard SOAP headers. For now, embrace the fundamental XML technologies and don't expect too much too soon.

Microsoft is actively working on a group of higher-level services known as GXA. Most GXA specifications are proposals for SOAP headers that provide another piece of the puzzle. The WS-I initiative will play an important role in defining additional Web Service profiles that reference such work. As standard SOAP headers evolve, the Web Services platform will come closer in functionality to the sophisticated but proprietary distributed platforms of the past.

Send your questions and comments for Aaron to xmlfiles@microsoft.com.

Aaron Skonnardis an instructor/researcher at DevelopMentor, where he develops the XML and Web Service-related curriculum. Aaron coauthored Essential XML Quick Reference (Addison-Wesley, 2001) and Essential XML (Addison-Wesley, 2000).