Web Services Design Tips - SOAPAction

Recently, I have been asked why a service was not working without the infamous SOAPAction, and I figured out I should try to explain it, one for all. Let me know if it works for you.
As the SOAPAction is transport specific -an HTTP header field, you should try to avoid it's use when authoring WSDL files for your new services, especially if you plan to use other transports for the same service. There are only a few usecases where you really need it: it's when you are using 'bare-style' document-literal binding or overloaded method (if your language of choice permit it).
The Key to this problem is to understand the relationship between the WSDL and the wire format, and to realize that the name of the wsdl:operation is not necessary present on the wire. Let's take an example to clarify this point. Here is a simple JAVA interface, that will be our samle code today:
Figure 1. Sample JAVA SEI
public interface SEI extends java.rmi.Remote {
public String lookupPhone(String eid)
throws java.rmi.RemoteException;

public String lookupEmail(String eid)
throws java.rmi.RemoteException;
}
This JAVA SEI can be converted into the following WSDL format.
Figure 2. Sample WSDL equivalent to the SEI
  <types>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetnamespace="http://ws.fusion.com/"
elementformdefault="qualified"
tns="http://ws.fusion.com/">
<element name="eid" type="string" nillable="true">
<element name="result" type="string" nillable="true">
</element>
</element>
<message name="lookupEmail">
<part name="eid" element="tns:eid">
</part>
<message name="lookupEmailResponse">
<part name="result" element="tns:result">
</part>
<message name="lookupPhone">
<part name="eid" element="tns:eid">
</part>
<message name="lookupPhoneResponse">
<part name="result" element="tns:result">
</part>
<porttype name="WrappedService">
<operation name="lookupEmail">
<input message="tns:lookupEmail">
<output message="tns:lookupEmailResponse">
</output>
<operation name="lookupPhone">
<input message="tns:lookupPhone">
<output message="tns:lookupPhoneResponse">
</output>
</operation>

Figure 3. Sample SOAP payload
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<env:Body>
<ans1:eid xmlns:ans1="http://ws.fusion.com/">eid</ans1:eid>
</env:Body>
</env:Envelope>

From the wire format above, once cannot tell is the message is targeted at the lookupEmail operation or at the lookupPhone operation. In order to route this message, you need extra information - it's the purpose of the SOAPAction header in the list displayed below.
Figure 4. Sample set of HTTP header
User-Agent: Oracle HTTPClient Version 10h
SOAPAction: "urn:lookupEmail"
Accept-Encoding: gzip, x-gzip, compress, x-compress
Content-type: text/xml; charset=UTF-8
Content-length: 302

The main reason the SOAPAction is used by most Web Services framework is as a performance optimization. It provides a key to lookup the operation where the message should be routed at, without to have to process the SOAP payload (the soap:body).

To sum up:
  1. use an empty value if you can.
  2. use it when you are using overloaded methods - the QName of the top-level element of the soap:body can be used to uniquely identify the operation that should process the incoming message.
  3. if you are after the performance boost, use a short value as it will also an impact too. No need to wait for the 69th caracther of the string before to find a charater that can be used to dicriminate from other values. Think tinyurl vs verbose text.

Note that this tips is specific to SOAP 1.1 and will not apply moving forward, as the routing attribute will be factored in the addressing header.

Happy Coding !

-Ecco

Comments

Anonymous said…
Thanks! I just spent time trying to figure out why the operation name wasn't in the soap message. Your explanation sums it nicer than the spec does.
Web design said…
Hi,
Thanks for your effective knowledge on Web design services.
It should be able to induce the reader to buy your products or services.
Craig J said…
Great info! Thanks. Now I can go back to ignoring the soapAction attribute.

Popular posts from this blog

Changing the version of JDK used by JDeveloper

Connection reset from a WCF Web Service

unexpected null value for literal data