It all comes down to application semantics.
One of the primary tenets of REST is the use of a uniform interface between components. In his dissertation on REST, Roy Fielding describes the uniform interface as "the central feature that distinguishes the REST architectural style from other network-based styles". REST is closely associated with the HTTP application protocol because HTTP provides this type of uniform interface -- all components communicate using simple, generic methods: GET, POST, PUT, and DELETE.
In Mark's post he explains the different application semantics expected when using POST versus PUT to send a SOAP message. POST implies "process this message", while PUT implies "store this message".
SOAP is also an application protocol, with its own set of application protocol semantics. And these semantics are different from HTTP application protocol semantics. Even though SOAP messages are typically transferred using HTTP, for the most part SOAP hides/obscures the HTTP semantics from SOAP applications. The underlying SOAP runtime systems communicate using HTTP semantics, but SOAP applications communicate using SOAP semantics.
SOAP uses (some would say abuses) the HTTP application protocol. Even though HTTP is an application protocol, SOAP treats HTTP as a lower-level communication protocol. But SOAP is an equal-opportunity application protocol abuser. SOAP treats other application protocols, such as WebSphere MQ, SMTP, and Jabber, the same way. From the SOAP perspective, these application protocols are all low-level communication protocols.
The SOAP specifications define bindings of the SOAP application protocol semantics to other application protocol semantics, such as HTTP, SMTP, and WebSphere MQ (communication protocols). Simply put, SOAP uses HTTP and other application protocols to exchange messages between SOAP nodes. The SOAP nodes act as mediators between SOAP applications and the underlying communication protocols. Although there are some subtle differences between the various protocol bindings, SOAP does a fairly decent job of isolating the applications from the different semantics of the various underlying communication protocols. (SOAP 1.2 does a better job than SOAP 1.1 abstracting away the underlying protocol semantics.) In any case, the goal is that SOAP exposes the same application protocol semantics regardless of the underlying communication protocol.
SOAP does not fully exploit the power of the HTTP application protocol. In fact, SOAP 1.1 explicitly constrains its use of HTTP to that of the HTTP POST operation. SOAP 1.1 over HTTP requires that SOAP requests be sent using POST. The specification doesn't indicate how to process requests using PUT. Therefore use of PUT is not supported by the SOAP protocol. SOAP 1.2 adds a description of using SOAP with HTTP GET, but it still doesn't describe how to use SOAP with HTTP PUT. Mark's example of using HTTP PUT to store a SOAP message is outside the scope of the SOAP protocol. In this example, HTTP PUT semantics apply, not SOAP semantics.
Now -- getting back to the topic of REST and SOAP and document-oriented web services ...
In his post, Mark references one of my responses to an Ask the Expert question on TechTarget regarding the difference between Document and RPC style services. In my response I indicated that the difference between Document and RPC is fairly minor, but the more import consideration is the encoding style. Document style messages are encoded literally according to a schema. Back in 2002, when I wrote this response, RPC style messages were typically encoding using a data model called SOAP encoding. (Many SOAP engines now also support literal encoding of RPC style messages.)
Mark has a different perspective, though. He claims that the more important difference between Document and RPC style services is whether or not the message contains a method name. When using RPC style, the message always contains the method name. When using document style, the message may or may not contain the method name. When using the "wrapped" programming convention, the message does contain the method name. When using the "unwrapped" programming style, the message typically doesn't contain the method name.
To quote Mark's post:
While the encodings used were certainly different, each with its own not-insignificant pros and cons, what Anne failed to point out is that the RPC example included an operation name (”placeOrder”) while the document oriented example did not. This constitutes an extremely significant architectural difference, as it tells us that Anne’s document example uses a state transfer style, while the RPC example does not.But I have to disagree with Mark's assertion. And here I have to go back to the differences between HTTP and SOAP application protocol semantics. Mark makes the assumption that if the message does not include a method name, then it must therefore be using a uniform interface -- an implicit "processMessage" operation. But that's not how SOAP works. SOAP doesn't require that you specify a method name in order to map the request to a specific method. Per the SOAP specification, the SOAP node determines what method to invoke based on the qualified name (QName) of the child element of the SOAP Body element. It really doesn't matter if the name of that element is a noun ("purchaseOrder") or a verb ("placeOrder"). The QName determines the action to be performed. These SOAP semantics are fundamentally different from HTTP/REST semantics.
In REST, the "method" that will be invoked is always determined by the URL to which the request is sent, not by the contents of the request message. REST has a uniform interface, therefore a POST to a URL will always invoke the implicit "processMessage" operation.
In SOAP, the "method" that will be processed is determined by both the URL to which the request is sent and the contents of the request -- the QName of the SOAP Body. So, for example, a single service might support multiple methods: placeOrder, cancelOrder, getOrderStatus. Each method is invoked by sending a different document:
- purchaseOrder invokes placeOrder
- canceledOrderID invokes cancelOrder
- pendingOrder invokes getOrderStatus