In this look at building interoperable Web services, the following items will be covered:
Best practices: Understand what you can do as a Web service creator to make it easier to use Web services for more end users
Interoperability Efforts
If you were an early adopter of Web services, you may have had problems getting two different SOAP stacks to talk to each other. You could have seen the problem with something as simple as a Web method that echoed back "Hello World!" Fortunately, that kind of experience is rapidly becoming a thing of the past. Why?
Today, there are two large efforts underway to ensure that the various vendors of SOAP toolkits are creating interoperable implementations. Web services stacks have little value if they can only interchange data between machines hosting the same SOAP stack. This was true before in the HTTP world and continues to be true today with SOAP. The two efforts are SOAPBuilders and the Web Services Interoperability Organization. Both groups exist to get the various implementations to work with each other. Their methods of achieving this goal are significantly different. They differ in many areas:
- Membership requirements
- Stated goals
- Community makeup
- Progress to date
In this section, we will take a look at these two complementary organizations and see how they, together, are going about making application integration through Web services possible. It's important to remember that many of the organizations represented in SOAPBuilders are also represented in WS-I.
SOAPBuilders
SOAPBuilders came into being January 30, 2001. A lot of the discussion that this group now hosts was hosted originally on the SOAP discussion list at
http://discuss.develop.com/soap.html. You can read the announcement of the new newsgroup here:
http://discuss.develop.com/archives
/wa.exe?A2=ind0102&L=SOAP&P=R506. This newsgroup exists because Tony Hong of XMethods actually acted on the idea of creating a new newsgroup. Why does this newsgroup exist? From the original message, Tony states, "The group was started to facilitate communication between builders of SOAP implementations, specifically about interoperability issues." Since then, the group has done quite a bit to make interoperability a reality. What have they done?
First off, three suites of interoperability tests have been defined. These tests can be thought of as progressively higher bars. The first set makes sure that basic data types can be exchanged without any issues. The second set makes sure that SOAP Headers as well as arrays and complex types can be exchanged by the SOAP stacks. These two sets of tests all use rpc/encoded message exchanges. The latest, third round of testing makes sure that document/literal encoding is understood. The tests also verify WSDL compatibility for the various SOAP stacks and helper tools.
So, how does a member of the SOAPBuilders community find out where other endpoints live? One way is through the mailing list at soapbuilders@yahoogroups.com or by searching the archives at
http://groups.yahoo.com/group/soapbuilders. Another is by looking at a page showing a list of endpoints:
The other thing the SOAPBuilders community does is get together for face-to-face events. These events are for developers only. Politicking is kept to a minimum. During these events, the developers representing the various SOAP stacks discuss what things to test next, discuss the specifications to arrive at a common understanding, and test the SOAP stacks in close proximity. This often results in significant headway taking place. In the February 2002 face-to-face, the Axis toolkit "learned" how to understand document/literal WSDL and messages. In the June 2002 face-to-face, the group discussed whether or not it would make sense to start adding programming concepts to the common vernacular of SOAP. One such example is dictionary types. A dictionary type is one that contains unique keys to lookup values. In Java, this is called a hashtable. In C++ and the STL, it is called std::map. In .NET, it's called a dictionary. No specifications exist (yet) to explain how one SOAP toolkit should represent a dictionary-data type. Still, this is something that the SOAPBuilders community is pondering.
In order to join the group and attend a SOAPBuilders face-to-face event, you should be involved in the development of a SOAP stack or set of SOAP tools. The only real membership requirements are a live endpoint that the development team is willing to host. To attend a face-to-face event, potential attendees need to do the following:
Bring a laptop, preferably with an 802.11b card. Wireless makes networking everybody much easier.
Why does all of this matter? As a Web service developer, I've found that using SOAP stacks that are actively involved in the SOAPBuilders community reduces interoperability pains. I have also discovered that it is very important to only use stacks that were released after the development team writing the stack got involved in SOAPBuilders. No involvement in SOAPBuilders typically means that I won't even bother with the stack.
And, in case you think SOAPBuilders is completely formal, the other reason for the face-to-face events is so that the community can get to meet. This way the people get to know each other. Oh, and it's really hard to be mean to a person you've had a few beers with.
Web Services Interoperability Organization
For all of its merits, SOAPBuilders is still an ad hoc organization with little formal backing. Also, it does not have obvious points of entry for system integrators, consulting firms, and others who use SOAP but do not create SOAP stacks. The Web Services Interoperability Organization (WS-I) was created to solve the interoperability problem in a different, more structured manner. The organization is creating profiles, sample applications, and testing tools for Web services. Let's take a quick look at these items.
A profile defines a collection of protocols and Web standards. A profile definition explains the types of solutions that combination of protocols can provide. The first profile that will come out of WS-I is called the Basic profile, located at
http://ws-i.org/docs/WS-I_Profiles.doc. The Basic profile essentially defines what it means to be a Web service. This profile includes the following specifications and standards:
- XML Schema 1.0
- SOAP 1.1
- WSDL 1.1
- UDDI 1.0
The profile will provide guidance about how to use the specifications. Things such as useful subsets, usage guidelines, and other information will appear in the profile documentation. Using the profile, WS-I will also produce a set of sample applications. The first set of sample applications will make use of SOAP over HTTP. Also, a set of testing tools and test suites are being created. The test tools consist of a message logger and an analyzer. The message logger captures messages and stores them in a message log. The analyzer reads the log and verifies that the messages conform to the specifications defined for the sample applications and the profile. These testing tools will be used by developers and customers to verify the correctness of implementations of the Web services sample applications.
To join WS-I, the potential member must sign a membership agreement and pay an annual membership fee. Members of WS-I will help to define and/or refine various standards around Web services.
Best Practices for Building Interoperable Web Services
How can you build an interoperable Web service? Most SOAP stacks allow a great deal of flexibility in sending and transmitting SOAP messages. Because of this flexibility, it is very easy for a developer to make some decisions that make sense for their preferred SOAP stack that wind up being difficult to use when going to another implementation. To increase the likelihood of getting a Web service to work with others, the developer needs to look at three primary things:
- SOAP stack being used
- XML Schema (XSD) describing the messages
- Usage of toolkit specific features
By being aware of all of these items when developing a Web service, the developer can spend more time coding and less time supporting end users.
Choosing a SOAP Stack
When you look for a SOAP stack, make sure that the one you choose to work with meets these requirements:
The SOAP stack interoperates with other active endpoints.
By following this advice, you will find that a number of simple interoperability problems will not surface. Surprisingly, this is the only nonintuitive thing to look for. From the list of participating options, choose one that supports the language and platform you prefer to work with. If you don't find a compatible toolkit, either pick a new language or prepare to develop one. While developing the new toolkit, make sure you join in with a community that does testing across Web service stacks. SOAPBuilders does this today. Other groups, such as WS-I, will have more advanced forms of interop testing in the near future.
While not a requirement, you will find that interoperability will be at its best if the particular SOAP toolkit has some form of representation in WS-I.org. The representation indicates that the organization behind the Web service implementation wants the interoperability to go deeper than things like "can the toolkit read and send a complex type." WS-I.org will look at the complete scenario: discovery, proxy generation, message exchange, etc., and make sure the toolkit can do it all.
Choosing a Data Representation
A good number of interoperability problems happen due to developer choices, not SOAP toolkits. Here is an example of a developer choice that results in a WSDL-type definition that is hard to use:
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="xsd:schema" />
<xsd:any />
</xsd:sequence>
</xsd:complexType>
When a client sees this definition, what should they do? It appears that the WSDL has stated something along the lines of "I will send you an XSD and an XML document that corresponds to that XSD." (That wasn't explicitly stated, but that's what this snippet is trying to express.) How do I code against this? Is this code simple or complex? What do I do? Here is another example of a hard-to-use WSDL definition:
<xsd:complexType name="Map">
<xsd:sequence>
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="key" type="xsd:anyType" />
<xsd:element name="value" type="xsd:anyType" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
Once again, I know that I am getting two items called key and value that are of type anyType. My guess as a developer is that this data is a dictionary datatype. What should I map the key and value elements to when I receive the data? I haven't got any contextual information.
In case you don't recognize the above snippets, the first one is the result of telling ASP.NET to return a System.Data.DataSet. The second one is an Apache SOAP serialization representation of java.lang.Hashtable. Instead of returning one of these non-interoperable types, you could choose to return something that is more likely to interop. For example, when returning tabular data, it is fairly unlikely that the number and names of the elements will vary based on inputs to the Web method. Most of the time, the tabular data will contain the same types. Instead of returning a generic type, the WSDL and corresponding source code could be modified to return something that other toolkits can more easily import and use. How could something like the ASP.NET example be improved?
Let's assume that the DataSet is populated with product data. I could define the array of data with the schema shown in Listing 1 .
Now, any consumers of the data know exactly what the response SOAP will look like. Instead of needing to process the returned message with XML, the client program could use native classes. Most SOAP toolkits are capable of translating between the XML and object representation of data. Well-defined WSDL allows the toolkit to generate these objects with no to little developer intervention.
You can get similar problems when just stuffing XML inside of the SOAP Header or Body. Unless the XML is really generic (and it rarely is), take the time to define what the WSDL will look like. Often, this choice is made when the developer knows things will be changing and they don't want to update the WSDL in order to change the code providing the Web service. Any time you change the way a Web service behaves, you will probably break a downstream client somewhere. Take a little extra time and define what the returned XML will look like. When you update the back-end Web service, plan some time in the schedule to write a new version of the WSDL.
Often, when using SOAP, the developer knows that they want to handle messages as raw XML. That's fine. Still, the returned XML will typically follow a set schema. Define that schema in your WSDL, even if you don't rely on object serialization/deserialization. Just don't take away the ability to generate smart clients from any end users. By providing schema, you make the end user's life much easier.
This last bit of advice invariably brings up the question: what should I do with two WSDL files? The issue: most people want to avoid having too many side-by-side versions of a Web service up and running. One solution is to have a regular release cycle and make sure that users of the Web service understand that the service will only be available for a fixed amount of time. For example, put documentation in the WSDL that states when the service endpoint will end service. If the Web service requires a preexisting arrangement (such as a signed contract) before a user begins accessing the service, put language in the contract explaining how frequently the Web service will be updated and how long any given version of the Web service will be available. This still means that you will wind up running multiple versions of the same Web service at the same time. Thankfully, it gives you a way of limiting how long versions need to be available.
Finally, since you are using WSDL and schema anyhow, you might as well code the Web service to emit a document/literal representation of the data instead of rpc/encoded. There are situations where rpc/ encoded still shines. Namely, if you are serializing a complex object graph and the relationships need to be maintained, use rpc/encoded. Otherwise, stick with document/literal representations of data.
Summary
To achieve Web service interoperability, the tools vendors have banded together and created two organizations: SOAP Builders and WS-I.org. SOAPBuilders is an informal group that works at getting fundamental issues around interoperability resolved. At the other end of the spectrum, WS-I.org provides a more formal structure that rigidly defines what it means to be interoperable and the set of protocols that are being worked on. WS-I.org provides architectural guidance, testing tools, and sample applications that aid in the understanding and adoption of Web services. We need both organizations to solve the issues around interoperability and Web service adoption and general understanding. Why? Some implementations of SOAP stacks, such as SOAP::Lite (Perl) and pocketSOAP (COM/PocketPC), may never have corporate backing. Implementations like these are valuable and need some forum in which to verify interoperability with the Web service stacks offered by corporate entities.
As a developer of Web services, you should take advantage of the work the interoperability groups are doing by only using SOAP toolkits that are actively involved in SOAPBuilders. It makes your life easier because you are using a toolkit that is being tested against other toolkits. Issues are discovered and fixed through this testing.
When developing a Web service, avoid declaring the return of generic XML in WSDL files. Instead, declare exactly what you are returning via schema and return that instead. Is generic XML useful in interop scenarios? Yes. But most scenarios do not require or benefit from the ability to send and read weakly expressed XML. Unless you really need that ability, express the format of the returned message in XSD contained or referenced from the WSDL description of the Web service.
About The Author
Scott Seely is a member of the MSDN Architectural Samples team. Besides his work there, Scott is the author of SOAP: Cross Platform Web Service Development Using XML (Prentice Hall PTR) and the lead author for Creating and Consuming Web Services in Visual Basic (Addison-Wesley). sseely@microsoft.com
Reproduced with permission from Microsoft Corporation
Building Interoperable Web Services, by Scott Seely
WSJ Vol 02 Issue 09 - pg.33
Listing 1
<xsd:complexType name="ArrayOfProduct">
<xsd:sequence>
<xsd:element minOccurs="0"
maxOccurs="unbounded"
name="Product" nillable="true"
type="s0:Product" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Product">
<xsd:sequence>
<xsd:element minOccurs="0" maxOccurs="1"
name="QuantityPerUnit" type="xsd:string" />
<xsd:element minOccurs="1" maxOccurs="1"
name="UnitPrice" type="xsd:decimal" />
<xsd:element minOccurs="0" maxOccurs="1"
name="CategoryName" type="xsd:string" />
<xsd:element minOccurs="0" maxOccurs="1"
name="SupplierName" type="xsd:string" />
<xsd:element minOccurs="0" maxOccurs="1"
name="Name" type="xsd:string" />
<xsd:element minOccurs="1" maxOccurs="1"
name="ID" type="xsd:long" />
</xsd:sequence>
</xsd:complexType>
All Rights Reserved
Copyright © 2004 SYS-CON Media, Inc.
E-mail:
info@sys-con.com