SOAP Worst Practices Part 3: Not Completely Specifying the Message Format

(This is the third in a series of articles that attempts to expose some of the more common mistakes and misunderstandings people make when implementing a SOAP Web Service.)

This is somewhat related to the previous post about trying to be too flexible. However, usually this problem is accidental, where the previous was intentional. This problem also is usually the result of misunderstanding or misusing a Web Services development tool.

XML has an element type called “any.” It basically means, “Anything that is valid XML is OK here.” It’s a way to make your document more flexible without the burden of defining type extensions. It should be used very sparingly though,  because the point of a structured data format like XML is to define a structure for a piece of data. When you use the “any” element, it completely ignores that point and allows any structure.

One cause of this problem is misuse of a Web service tool. There are many tools available to ease your creation of Web services. There are tools for most programming languages where you can hand it a business object, and it will generate a WSDL that defines an XML version of that object, and even the code to handle transferring it and converting it into the actual object. You just then need to write the code that does the real work. The tool does all the mundane communication work.

For example, suppose we are creating an order entry system. We design a PurchaseOrder business object. This example uses .NET, but there are tools for other languages as well. Here are our purchase order business objects:

<code>
public class PurchaseOrder {
public int poNum;
public String custNum;
public DateTime orderDate;
public List<PurchaseOrderLineItem> lineItems;
}
public class PurchaseOrderLineItem {
public int itemNum;
public String itemName;
public decimal price;
public int qty;
}
</code>

In .NET, we can use a WebMethod to have all of the Web services communication code generated for us. This is great because we really want to spend our time developing the business logic of our applications. Communications are a necessary but somewhat menial task that can and should be automated when possible. This brings us to the root of the problem with this SOAP Worst Practice. Suppose we write our method as follows:

<code>
[WebMethod]
public string receivePurchaseOrderBAD(XElement poXML) {

}
</code>

This looks OK at first glance. Yes, we’re using SOAP, which uses XML, and so we should take this XML element as a parameter. While this is valid code, and it will run, it causes a number of problems. First, it generates a very generic WSDL using the “any” element discussed earlier:

<code>

<s:element minOccurs=”0″ maxOccurs=”1″>
<s:complexType>
<s:sequence>
<s:any processContents=”lax” />
</s:sequence>
</s:complexType>
</s:element>

</code>

This makes client implementation very difficult, because the WSDL says nothing about the structure of a purchase order. Unless we have knowledge of the internal server program, we can only guess at the format. It is next to impossible.

Second, it makes the server program much more difficult to write. Because we are receiving an XML element as a parameter, we must write the code ourselves that parses the XML and extracts the data, and constructs our PurchaseOrder business object:

<code>
public PurchaseOrder(System.Xml.Linq.XElement po){
poNum = (int)po.Element(“poNum”);
orderDate = (DateTime)po.Element(“orderDate”);
custNum = (string)po.Element(“custNum”);
lineItems=new List<PurchaseOrderLineItem>();
foreach (System.Xml.Linq.XElement lineItem in po.Descendants(“LineItem”)){
lineItems.Add(new PurchaseOrderLineItem(lineItem));
}

</code>

This is very tedious and error-prone.

Instead, our Web method should look like this:

<code>
[WebMethod]
public PurchaseOrderAck receivePurchaseOrderGOOD(PurchaseOrder po){

}
</code>

Note that this time we selected PurchaseOrder as the parameter instead of the XML element. This is where the true value lies in using a tool like .NET. First, it will generate a meaningful WSDL:

<code>

<s:complexType>
<s:sequence>
<s:element minOccurs=”1″ maxOccurs=”1″ />
<s:element minOccurs=”0″ maxOccurs=”1″ />
<s:element minOccurs=”1″ maxOccurs=”1″ />
<s:element minOccurs=”0″ maxOccurs=”1″ />
</s:sequence>
</s:complexType>

</code>

Note the details are fully included. This means that any client that wants to send us a purchase order can do so just by looking at this WSDL. It has all the information needed for them to create an xml document that fits our structure and will be accepted by our server.

Second, we do not need to write any XML parsing code as in the first example. .NET does all of that for us, creating and fully populating our PurchaseOrder business object, ready for us to use to do the real work. This is much easier, faster, and safer of a solution.

I’m making my simple example project available here. You’ll need a .NET development tool to use it. I used Visual Web Developer Express, available as a free download from Microsoft here. Once you have your system set up, open the WebService2.sln file. Press Ctrl-F5 to run the example, and it will bring up a Web browser displaying the details of the Web service methods. Try calling the good and bad versions from your favorite Web service tool (e.g., SoapUI or even EBI’s own Web Service Consumers) and see for yourself what the difference is.

One thought on “SOAP Worst Practices Part 3: Not Completely Specifying the Message Format

  1. Pingback: Tweets that mention SOAP Worst Practices Part 3: Not Completely Specifying the Message Format | EXTOL Technology Blog -- Topsy.com

Leave a Reply

Your email address will not be published. Required fields are marked *


*