Menu

SOAP 1.2

June 10, 2003

Rich Salz

W3C Process

As you may know by now, SOAP 1.2 has reached Proposed Recommendation (PR) status, which means that the XML Protocol Working Group believes that it's done. A few PR issues have been raised. It can be fun to look at the list, as the issues range from "I found a typ" to "this isn't full XML, send it back to the committee". If you're pedantically inclined -- and everyone in the computer field must have at least some inclination in that direction -- now is the time to break out the coffee and the reading glasses in order to find issues of your own.

Within the next week or two, we should know if Tim Berners-Lee approves the PR, making it a formal W3C Recommendation (i.e., a standard in everything but name); or, if he identifies issues that need to be resolved, requiring another round of work. The results could be interesting: there are, as usual, a number of political issues involved.

First, the WG is clearly done. It met the requirements, addressed the hundreds of issues filed, and wrote a set of documents that definitively and comprehensively defines a plausible evolution of SOAP 1.1. Second, there are several influential individuals who are adamantly opposed to the current Web Services framework and its SOAP underpinnings. For example, consider a Mark Baker's blog item, titled " Gauntlet Tossing" or Elliotte Rusty Harold's PR issue. Third, SOAP and SOAP 1.2 represent a significant corporate involvement, and it would be risky for the W3C to force that train to make a pit-stop. Last, most people like to feel that they're being told what to do, and they often get persnickety about it.

Infoset: Not the Root of All Evil

The biggest difference between SOAP 1.1 and SOAP 1.2 is that the 1.2 specification is built around the Infoset. Last November, I wrote a column about why this is bad. If only out of fairness, we should now look at why it's good.

The descriptions SOAP message processing are no longer based on syntax but on the information that the message carries. An implementor can determine what information items are important and must be preserved. It's now feasible to understand how to "tunnel" a SOAP message safely over any appropriate transport. Following the logic, you can know see that SOAP is now much more transport-neutral.

With any luck we'll see a wide variety of environments supporting SOAP messages in a very powerful way; as much as possible, they will look like native messages within the environment, but they'll be able to cross that environment and be safely converted to "classic HTTP/SOAP" without any information loss. In other words, I can have HTTP-based servers at each end of a processing pipeline, but have MQ, SMTP, CORBA/IIOP, or other intermediaries doing parts of the processing along the way.

If the middleware vendors follow through on that promise, we really will have a universal distributed messaging infrastructure. I'm actually fairly optimistic about this, since it seems the only way that proprietary middleware stands a chance of not being wiped out completely by HTTP plumbing and WS-xxx headers commoditizing their value-add for items like reliable transport.

The relationship between SOAP, MIME, and HTTP has been cleaned up. Most SOAP developers will probably never notice this, but it's a good thing. IETF RFC 3023 defined a set of MIME media types for XML and a "+xml" suffix convention for new types that are XML based but have special processing requirements or implications. SOAP 1.1 used application/xml or text/xml, which meant that a browser (or server) couldn't distinguish between an XML document and a SOAP message. SOAP 1.2 defines the application/soap+xml media type. As part of this registration, the SOAPAction header has become an "action" parameter in the MIME type. Developers might notice this, and might find their situation improved, since it's often easier to get control over the MIME bits than the HTTP bits when they're developing applets or servlets.

To summarize, while SOAP 1.1 would have these HTTP headers:

Content-Type: text/xml

SOAPAction: "http://example.com/ticker"

A SOAP 1.2 message would have the following:


Content-Type: application/soap+_xml; action=http://example.com/ticker

Moving all of the metadata into the one place where it should be is also a good thing.

New Head

The true genius behind SOAP is the SOAP:Header element. By requiring all top-level elements in the header to be namespace qualified, the SOAP header provides a consistent place to put messaging metadata in a way that is guaranteed to not conflict. If SOAP survives into the next century, it's because the Federation will have defined a header that handles tachyons and time-travel:

    <tns:Ordering SOAP:mustUnderstand='true'>

        <tns:ReplyBeforeRequest value='never'/>

    </tns:Ordering>

More seriously, there are already over a dozen specifications that define SOAP header elements to provide message routing, transactional semantics, message security, and so on. This will undoubtedly continue, as vendors use this mechanism to provide their own special features, admittedly sometimes with the goal of locking-in customers to a specific implementation of this open standard.

SOAP 1.1 defined actors as intermediary processing agents that would perform actions based on SOAP headers that were targeted to them according to the URI value of the actor attribute. SOAP 1.2 cleans up this language by renaming the attribute to role, reinforcing the notion that the header is intended for a particular type of processing. The improvement becomes obvious when you realize that a single SOAP processor can function in multiple roles, but it's harder to think of the same processor action as different actors.

SOAP 1.2 also defines two new roles. The first is none, which is used to specify a header that no intermediary should process, although they may need to examine the contents if another header directs them there. The second, ultimateReceiver, is used to explicitly mark a header as intended for the final recipient of the message. As with SOAP 1.1, this is the default if no role (actor) is specified.

SOAP 1.1 was somewhat ambiguous about header processing. For example, suppose the message arrived at its final destination, and it had headers with mustUnderstand="1" that were targeted to actors that the final recipient didn't support? Some argued that this was an error, since the proper intermediaries never saw the message, and that the ultimate recipient should send a fault back. Others felt that the specification was vague, that processing could start before the application realized some headers were there, and that it was too expensive to require a pre-scan. In addition, the header could be processed and then reinserted by the actor.

SOAP 1.2 introduces the relay attribute to make this explicit. If a processor sees a header with a role that it supports, the relay attribute indicates whether unprocessed headers should be forwarded or stripped. This attribute, particularly when used with mustUnderstand, allows a sender to assert fine-grain control over all header processing. The semantics of mustUnderstand have not been changed in SOAP 1.2, although the values have been changed from 0 and 1 to true and false.

Whose Fault?

Arguably the most visible change to SOAP developers is that the format of a SOAP fault has changed dramatically. First, the client and server terms have been renamed to the more-appropriate sender and receiver. The Java-style dot notation for fault codes (e.g., Client.Authentication) have been replaced with XML qnames and an initial set of fault codes are defined in the SOAP 1.2 namespace.

To get extensibility in faults analogous to the old dot notation, a Subcode element is defined. For example, an authentication failure could include this fragment:

    <SOAP:Code>

      <SOAP:Value>SOAP:Sender</SOAP:Value>

        <SOAP:Subcode>

          <SOAP:Value>saml:Unauthenticated</SOAP:Value>

        </SOAP:Subcode>

    </SOAP:Code>

New subelements allow multilingual text reasons to be provided and a placeholder for arbitrary XML details.

    <SOAP:Reason>

      <SOAP:Text xml:lang="en-US">Invalid login</SOAP:Text>

      <SOAP:Text xml:lang="Igpay-Atinlay">Invaliday

      oginlay</SOAP:Text>

    </SOAP:Reason>

    </SOAP:Detail>

      <... arbitrary XML here ...>

    </SOAP:Detail>

More from Rich Salz

SOA Made Real

SOA Made Simple

The xml:id Conundrum

Freeze the Core

WSDL 2: Just Say No

Hopefully SOAP endors will make it easy to generate and parse these new formats: having multilingual server error messages can be a big win, although knowing what language to output might require close integration with the transport layer.

From the developer's perspective, however, at least initially the major difference between SOAP 1.1 and SOAP 1.2 faults is that SOAP 1.2 does not use HTTP status code 500 (server error) to indicate a fault. As far as HTTP is concerned, a fault is a normal HTTP response message and is an accommodation to the principles of REST. It will have interesting implications for programmers who write their own SOAP stacks.

Finally, the most most important change of all: As explained in section 6 of the SOAP 1.2 Primer: "SOAP 1.2 will not spell out the acronym".