What's the problem these two specifications are trying to solve?
Networks sometimes fail -- it's just a fact of life that you, as a Web user, have come to live with. Having to hit the Reload button on your browser because you got back some vague Internal Server or Server not found error (when you know that Yahoo! didn't just fall off the face of the earth) are annoyances that you've just come to live with. And for the most part, hitting F5 really is ok -- maybe not on the Buy It page because you don't know if the system bills your credit card twice, but for most cases, it works just fine. However, when machines talk to one another, unlike humans, they're usually not just wandering (or surfing) for the heck of it. They have a very specific task to perform and detailed pieces of data to share. Losing any of those messages can result in serious consequences. Banks, for example, have spent extraordinary amounts of money (and time) making sure that the transactions/messages between their various computer systems are never lost. In other words, they want to make sure their data is reliably delivered to the proper destination. As Web services/Simple Object Access Protocol (SOAP) continues its ever expanding use throughout the industry, the need for guaranteed delivery in an interoperable way becomes vital to its success.
One approach to this problem is to send a message to a server and wait for the response. If you do not receive a response from the server after a certain amount of time, then resend the message. Problems do exist with this approach. First, if the messages are not being sent following the request-response messaging pattern (for example, they are one-way messages), then receiving back the HTTP 200 or 202 response code doesn't necessarily guarantee that the server received the message. By definition, 202 means that the message was simply Accepted at the HTTP layer and not necessarily processed by the SOAP processor. Also, a client SOAP stack might interpret one-way messages differently. For example, it might just open the connection and send the message without regard for the success or failure of the send (fire and forget).
And then, of course, there are those cases where the client notices the error response code; you can't simply retry. Getting back a response code other than HTTP 200 doesn't guarantee that the server didn't successfully deliver the message. As an example, perhaps the server receives the message and processes it correctly, but something goes wrong while trying to process the response message. By resending the message due to an HTTP 500 response code, the sever processes the message twice -- which could have very serious negative side effects.
Another approach would be to require all application messages to have some sort of response message. This would allow you to receive an acknowledgement or receipt of delivery even if response message is empty. Keep in mind that this approach helps you get confirmation of delivery (in the successful cases), but it doesn't help the problem of possibly the same message being delivered twice -- as I discussed in the previous paragraph. In order resolve this problem, the application would have to have logic to ignore duplicate messages -- not impossible but definitely annoying. Ideally, the development of any solution should occur at a level below the application, leaving it free to focus on its real job. In order to guarantee delivery of messages and one-time delivery, some amount of hand-shaking between the client and server is required. Since one of main goals of SOAP is interoperability between varying SOAP stacks, this hand-shaking needs to be an industry standard -- and of course, this means yet another WS-* specification. The Web services community doesn't have just one specification to solve this problem, they have two: WS-ReliableMessaging (WS-RM) and WS-Reliability (WS-R). Before I talk about the differences between these two competing specifications, let's first talk about their similarities, since they both basically solve the problem of ensuring reliable delivery of SOAP messages in the same conceptual way.
Both of these specifications allow SOAP stacks to push this problem down to a lower level, in particular, to the middleware layer. Once the application hands its message over to the SOAP stack, it can basically forget about it -- it's a guarantee that the SOAP stack will deliver the message to its proper destination -- sort of. You might encounter times when the SOAP stack cannot reach the destination endpoint for a message. In those cases, the client SOAP stack needs to notify the sending application of the failure -- but these are unrecoverable errors. For example, take the simple case of a typo in the destination URL. There is no way a SOAP stack could ever recover from that. The design of these reliable delivery specifications allow messages to reach their ultimate destination for cases where temporary network glitches occur. Both specifications talk about guaranteeing successfully delivery of messages or a fault generates as a result -- those are the only two possible outcomes.
The basic idea behind both specifications is the client (or sender) of a message continually resends the message until it receives confirmation (or acknowledgement) that the server (or destination) successfully receives the message. Not unlike one of the possible solutions discussed earlier. However, this also assumes some common understanding between the two endpoints. First is the definition of this Acknowledgment or ACK; both SOAP stacks must understand what an ACK is: what it looks like, what it means, and how to send it. Second, both sides must agree on the semantics of how to send the messages. As mentioned earlier, the sending side must agree to continually resend a message until it receives an ACK for that message. Likewise, the receiving side must not only agree to send back an ACK once they receive a message, but they must ignore any duplicate messages. At its heart, that's really all there is to both specifications -- let's now walk through an example to fully demonstrate how it works. For the examples, I'll use XML snippets from WS-RM. Later on I'll talk about how WS-R differs.
Figure 1 below illustrates a simple diagram reinforcing the message flow just discussed. Notice how a sender sends three messages as part of a single sequence. Both specifications have the concept of grouping a series of messages together so that you can not only guarantee their delivery, but also the order in which they are delivered (there might be cases where processing Message 2 before Message 1 could have serious consequences). In Figure 1, you see that only Messages 1 and 3 were successful on the first attempt of the three messages sent.
Figure 1. Basic reliable delivery message flow
After the first set of messages, notice how the destination sends back an ACK indicating that it received Messages 1 and 3 -- the sender now knows that it needs to resend just Message 2. And finally, upon receipt of Message 2, the destination can now send back one final ACK indicating that it received all three messages for this sequence. One additional thing to make note of, Message 3 was tagged as the last message of the sequence. This information can be used any number of ways. At a minimum, it allows the destination to know the highest message number in the sequence so it can return a Fault if it receives any messages with a number greater than three.
Now let's take a look at what these messages look like using WS-RM. First, let's start with Message 1, as shown in Listing 1 below.
Listing 1. Sample WS-RM message
<soapenv:Envelope>
<soapenv:Header>
<wsa:MessageID> ... </wsa:MessageID>
<wsa:To> ... </wsa:To>
<wsa:Action> ... </wsa:Action>
<wsa:From> ... </wsa:From>
<wsrm:Sequence soapenv:mustUnderstand="1">
<wsu:Identifier>
http://www.ibm.com/guid/a8f7151a091b50a42b38e04437774e11
</wsu:Identifier>
<wsrm:MessageNumber>1</wsrm:MessageNumber>
</wsrm:Sequence>
</soapenv:Header>
<soapenv:Body> ... </soapenv:Body>
</soapenv:Envelope>
|
The <wsrm:Sequence> header is the additional WS-RM specific data that is included as part of the message. Inside this header is a unique identifier for the sequence, allowing the destination to know which (of possibly many) sequence this message belongs to. And the other bit of data is the MessageNumber element -- indicating that this is Message 1. Hopefully, this should seem fairly straightforward -- the specification authors (of both specs) did a good job of keeping their solutions uncomplicated.
In Listing 2, the XML of Message 2 looks the same except for replacing the "1" with a "2" in the MessageNumber element. Message 3 is almost the same with one minor tweak:
Listing 2. Last WS-RM message in a sequence
<soapenv:Envelope>
<soapenv:Header>
<wsa:MessageID> ... </wsa:MessageID>
<wsa:To> ... </wsa:To>
<wsa:Action> ... </wsa:Action>
<wsa:From> ... </wsa:From>
<wsrm:Sequence soapenv:mustUnderstand="1">
<wsu:Identifier>
http://www.ibm.com/guid/a8f7151a091b50a42b38e04437774e11
</wsu:Identifier>
<wsrm:MessageNumber>3</wsrm:MessageNumber>
<wsrm:LastMessage/>
</wsrm:Sequence>
</soapenv:Header>
<soapenv:Body> ... </soapenv:Body>
</soapenv:Envelope>
|
In this message, you see that the WS-RM sequence header also includes a LastMessage element -- indicating that this is the final message in the sequence. Again, nothing too complicated. Now let's see what the destination's ACK looks like:
Listing 3. WS-RM SequenceAck
<soapenv:Envelope>
<soapenv:Header>
<wsa:MessageID> ... </wsa:MessageID>
<wsa:To> ... </wsa:To>
<wsa:Action> ... </wsa:Action>
<wsa:From> ... </wsa:From>
<wsrm:SequenceAcknowledgement>
<wsuu:Identifier>
http://www.ibm.com/guid/a8f7151a091b50a42b38e04437774e11
</wsuu:Identifier>
<wsrm:AcknowledgementRange Lower="1" Upper="1"/>
<wsrm:AcknowledgementRange Lower="3" Upper="3"/>
</wsrm:SequenceAcknowledgement>
</soapenv:Header>
<soapenv:Body> ... </soapenv:Body> (response body)
</soapenv:Envelope>
|
When the destination formulates its response, it includes an additional SOAP header (the ACK) in the message. As shown in Listing 3 above, you see that it includes the identifier for the sequence and two AcknowledgementRange elements. You?ll notice that destination received Messages 1 and 3 only. In the case of a request-response messaging pattern, you can piggy-backthis ACK on one of the response messages. For one-way messages, the destination SOAP stack needs to generate a new SOAP envelope (with an empty soapenv:Body) in order to add this ACK header. Actually, this grossly oversimplifies how to send ACKs back to the sender since both specifications make it possible to send the ACKs to a completely different endpoint from the sender. But for now, it's sufficient knowing that the ACKs are sent to the appropriate place.
So to complete the scenario, upon receipt of this ACK, the sender resends Message 2 and eventually gets an ACK, as shown in Listing 4 below:
Listing 4. Final WS-RM SequenceAck
<soapenv:Envelope>
<soapenv:Header>
<wsa:MessageID> ... </wsa:MessageID>
<wsa:To> ... </wsa:To>
<wsa:Action> ... </wsa:Action>
<wsa:From> ... </wsa:From>
<wsrm:SequenceAcknowledgement>
<wsuu:Identifier>
http://www.ibm.com/guid/a8f7151a091b50a42b38e04437774e11
</wsuu:Identifier>
<wsrm:AcknowledgementRange Lower="1" Upper="3"/>
</wsrm:SequenceAcknowledgement>
</soapenv:Header>
<soapenv:Body> ... </soapenv:Body>
</soapenv:Envelope>
|
This ACK indicates that all messages have been received. As mentioned earlier, if the additional logic (retries) ends up in the middleware layer, the SOAP stacks on both sides of the connection can manage the reliable delivery (and ordering) of messages without any changes to the applications.
The XML snippets are from a use of WS-RM. WS-R follows the same basic design, but its XML looks slightly different. However, differences do exist between the two specifications that are worthy of mentioning:
This specification:
- Allows for an optional createSequence message exchange before the application messages and an optional terminateSequence message exchange after the application messages. This bookending of the application messages allows for the destination to explicitly define the sequence identifier the sequence headers use. And by the client sending a final terminateSequence message, the destination knows that all of the ACKs have been received and can now forget about the entire sequence. By using the createSequence operation, the destination can be set up to reject any sequence that it doesn't have prior knowledge of -- a security benefit.
- Makes use of the WS-Addressing specification.
- Has the notion of a NACK. This allows the destination to send a notification to the sender to say which specific message needs to be resent. This allows for a more optimized resend algorithm.
- Has not been submitted to a standards body (such as World Wide Web Consortium (W3C) or Organization for the Advancement of Structured Information Standards (OASIS)), yet.
This specification:
- Allows the sender to include delivery assurance rules as part of the message. For example, it can include information indicating that the messages should be delivered "in order" and to ignore duplicates. WS-RM has these same delivery assurance rules, but they are not part of the messages. They are identified through some other means -- such as WS-Policy.
- Allows the sender to poll the destination for the ACKs. This enables a sender, that is behind a firewall, to still receive ACKs. WS-RM doesn't define any way for this sender to asynchronously receive ACKs. They must go back on the HTTP response flow or to an endpoint outside the firewall.
- Doesn't rely on WS-Addressing.
- Is an OASIS standard.
While the list of differences is short, it does illustrate the similarities between the two specifications. In fact, they both offer comparable features. So, why are there two? Which one should you use?
The short answer to the first question is that two different groups of companies decided to attack the problem in parallel and independently. The fact the two specifications ended up looking so much alike is actually a good indication that both groups of authors were on the right track.
Which one to use? That's a harder one -- for obvious reasons. Despite my affiliation with IBM® (IBM is one of the authors of WS-RM), I do prefer WS-RM. It's more consistent with the overall direction of the other WS-* specifications being adopted by the industry (like WS-Addressing). That being said, I do believe (or maybe it's just a hope) that at some point both groups will combine their efforts and produce a single specification. Not only because taking the best of both specifications will produce an even better solution, but because the Web Services community should not be forced to make this choice at all.
Perhaps it's inevitable as you move up the processing stack that different groups of companies will want to solve these types of problems in their own way -- leading to more choices like these (look at WS-RF verses WS-Transfer as another example). But the Web services community must remember one of the original selling points of SOAP: interoperability. If they allow duplication of effort, design, and specifications to become common place, they'll lose one of the biggest benefits of SOAP -- opening the door for something new to come along.
If you're interested in playing with WS-RM, take a look at the Emerging Technologies Toolkit. The toolkit contains a demo and some samples that allow you to experiment with the technology. There's also a demo Web site that uses the WS-RM interoperability workshops scenarios as its base. Check it out if you want to see WS-RM in action without downloading and installing anything.
- Get the following specifications:
- Visit Web sites of the most significant organizations where XML standards are developed:
- World Wide Web Consortium (W3C)
- Organization for the Advancement of Structured Information Standards (OASIS)
- Check out the WS-RM interoperability demo on IBM alphaWorks®.
- Browse for books on these and other technical topics.
- Want more? The developerWorks SOA and Web services zone hosts hundreds of informative articles and introductory, intermediate, and advanced tutorials on how to develop Web services applications.
- The IBM developerWorks team hosts hundreds of technical briefings around the world which you can attend at no charge.





