Designing Your Web Service for Maximum Interoperability
December 5, 2001
At this year's Professional Developers Conference (PDC), I convinced the Microsoft® ASP.NET folks to let me put together a demonstration of SOAP interoperability for the show floor. I'm not too sure whether they let me do it because it was a good idea, or because I would essentially be a full-time body in the booth. Regardless, someone was always waiting to see the demo and ask questions.
The demo itself was an extension of the IBuySpy sample Web site. IBuySpy shows how to build a Web application using ASP.NET and takes care of gathering an individual's orders. This demonstration went behind the scenes to the warehouse and showed a simplified vision of how the order might be picked. This example existed only to showcase SOAP interoperability. Any other details were bonuses.
The demonstration showed an Intermec 700 (essentially, a PocketPC in an industrial housing) using pocketSOAP. This unit allows the user to ask what item needs to be picked next, as well as to scan the barcode of the item and communicate that an item was picked. The PocketPC communicated with a Unix PC running Apache Tomcat and Apache SOAP. This unit's responsibilities include knowing which radio is picking what items, and to interface with the host computer running the IBuySpy Web Services.
Finally, the IBuySpy demo ran on a Microsoft® Windows® XP Professional system. I created a few add-ons to make it work for the demonstration. This primarily involved adding a few stored procedures, modifying some database tables, and adding a new Web Service. The system layout is shown in Figure 1.
Figure 1. Setup of demonstration at PDC 2001. The picture of the Intermec 700 is a photo of the actual product!
So, how does all of this tie into this column? While developing this demonstration, the earlier SOAP interoperability column, and a whole host of SOAP interoperability Knowledge Base articles, I got to see what works and what does not work between a variety of SOAP toolkits. The upshot is that I have discovered a number of things you can do to improve the ability of other toolkits to interoperate with Microsoft-based Web Services.
This is the easiest thing you can do to make your Web Service usable by other SOAP clients. How you do this depends on the tools you use to handle Web Service requests. Most developers using the Microsoft platform either use the Microsoft® SOAP Toolkit v2 or ASP.NET.
To make sure that the SOAP Toolkit emits type information, you will need to edit the type information of the XML Schema Definition (XSD) types in the Web Services Description Language (WSDL) file to read xsd:anyType. You do not need to alter the information on the type being received. Just edit the return type information. For example, if the WSDL file defines a response message type like this:
<message name='AddServer.AddResponse'> <part name='Result' type='xsd:int'/> </message>
Then you just need to edit the type attribute so that the message looks like this:
<message name='AddServer.AddResponse'> <part name='Result' type='xsd:anyType'/> </message>
Returning complex types typically requires extra work on the part of the user anyhow. As a result, I would only worry about these changes when the Web Service returns a simple type.
If the SOAP toolkit is a client, and you are using the high-level interface, and you are communicating with a toolkit that requires type information (such as Apache SOAP), then you need to make these changes to the request message so that it emits type information.
ASP.NET-based Web Services are a bit easier to handle in this respect. To make sure that ASP.NET uses RPC/encoded messages, just use the following code:
[System.Web.Services.Protocols.SoapRpcService] public class YourService : System.Web.Services.WebService
The attribute SoapRpcService tells ASP.NET to expose the Web Service and any exposed Web Methods as RPC/encoded. Alternatively, you can individually set the methods as RPC/encoded by applying the SoapRpcMethod attribute. For the time being, I recommend sticking with the SoapRpcService attribute, since it applies to the entire class and requires less work.
Provide WSDL Documents
Most of the toolkits available today do know what to do with a WSDL file. By providing these, you make it easier for others to use your Web Service. The toolkits can create a proxy, like what is done for the Microsoft® Visual Studio® .NET clients and Apache SOAP 2.2 clients. Alternatively, the proxy can be dynamically generated. We see this behavior in the high-level API of the Microsoft SOAP Toolkit 2.2, as well as in other toolkits such as SOAPy and SOAP::Lite.
If a proxy cannot be generated, the WSDL file does describe, in detail, exactly how you expect a client to interact with your Web Service. If the developer on the other end has learned how to read a WSDL document and understand its meaning, you have given them all the information they need in order to be able to access your Web Service. (Yes, user documentation is still beneficial and a Good Idea™).
XSD 1999 or 2001?
Once upon a time, a nasty compatibility issue reared its ugly head. ASP.NET Web Services would only generate WSDL files using the final XSD recommendation, which used a URI of http://www.w3.org/2001/XMLSchema. The IBM Web Services Toolkit and other SOAP toolkits would see this namespace and refuse to even try to understand the WSDL file. (Note: I only mention the IBM Toolkit because of its tight ties to the Apache SOAP implementation, and that implementation's high popularity in the Java community.) Other toolkits handled this issue in a variety of ways. A typical mechanism was to offer the ability to generate WSDL as either a working draft, using the http://www.w3.org/1999/XMLSchema. Another was to generate WSDL as a final recommendation using the 2001 version.
Due to the popularity of the Java toolkit, this was a big issue until recently. Why? Until the release of the IBM Web Services Toolkit 2.4.2 on November 16, 2001, this choice mattered when generating SOAP proxies. At this point in time, I am unaware of any tools that have issues with the 2001 XSD declaration. So, stick with 2001 XSD and you should be just fine. As a matter of fact, I suspect that the older implementations may start having problems if they emit 1999 XSD-related elements for much longer.
Avoid HTTP/GET and HTTP/POST Bindings in Your WSDL
If you use the SOAP Toolkit, this is easy. But what do you do if you use Visual Studio .NET to generate your WSDL files? You can disable all generation of the HTTP bindings by modifying your Web.config file. In the Web Service project, go into the
<configuration><system.Web> section and add the following lines of XML:
<webServices> <protocols> <remove name="HttpPost" /> <remove name="HttpGet" /> </protocols> </webServices>
These few lines tell the WSDL generator to not produce the HTTP/POST and HTTP/GET bindings. Why do you need to remove these bindings? Most of the existing toolkits do an excellent job of handling SOAP and many can even handle WSDL files. The developers of these toolkits did not worry about the existence of HTTP/POST and HTTP/GET bindings. They didn't have to because not many toolkits supported the binding in the first place. When the toolkits try to create proxies and see the bindings to HTTP/GET or POST they typically fail to produce anything. By telling ASP.NET not to provide those bindings, you make it easier for other toolkits to use your Web Service.
Use Proxy Generators
Whenever possible in your own work, try to use the proxy generators included with the various toolkits. The Microsoft SOAP Toolkit v2 has the high-level API, ASP.NET has WSDL.EXE from the command line and "Add Web Reference" from the IDE. .NET remoting has SOAPSUDS.EXE. Many of the other toolkits offer similar services. By using a proxy generator, you may have to do some specialized tweaking to get things to work right. These tweaks may occur in the WSDL file or in the generated code itself. Regardless, my experience has shown that using the helper tools eliminates more problems than they cause. By using them, endpoints are hooked up right and the messages are formatted correctly a lot sooner.
How does this enhance interoperability? Not at all. Instead, it reduces the chances for user error and improves your experience when using a technology that does a very good job of playing with others. If you do things the hard way and they wind up taking more time, don't say you weren't warned!
There are still some things that can give you potential trouble. Not all implementations agree on how SOAP headers are to be handled, in particular the mustUnderstand and actor attributes. This is getting better, but hasn't reached "bliss" yet. Also, avoid sparse arrays, as many implementations choke on these as well.
Newer protocols, such as those rolling out for the Global XML Web Services Architecture, may be something that you want to avoid for a little while until interoperability testing is underway for the protocols. If interoperability with these protocols is needed, I'd advise that you wait until interoperability efforts have been underway for at least a few months. Monitor progress on how things are going, and when the discussions start to indicate that interoperability is being achieved, that's a good time to jump in and start using the technology. If you are an early adopter, make sure that any clients know what implementation you are using. Armed with this information, they can either use the same platform or learn what the workarounds are to get the two toolkits to communicate.
SOAP is a simple protocol that relies on a large number of existing technologies. Some of the kinks are still being worked out, and it will take time before everything works perfectly. In the meantime, there are a few things you can do to help make the different toolkits supporting SOAP work well together. By using RPC/encoded messages where possible, supplying WSDL documents, and sticking to SOAP bindings only, you will find that many toolkits will be able to work with your deployed Web Services today. Moving forward, interoperability will get better, and many of these tips will become unnecessary. For example, the benefit of going with only RPC/encoded messages will be falling by the wayside when the Apache Group releases Apache Axis, the successor to Apache SOAP 2.2.
In two weeks, Matt Powell will return to talk about debugging production problems. It's something we have had to do a time or two with the Cold Rooster Web site.
At Your Service