RE: Thoughts on urlReplacement, REST, and R085

Mark,

Thx for the feedback.

In a separate piece of work Philippe and I have revised the HTTP binding 
for WSDL 1.2. In WDSL 1.1 the HTTPbinding  used either GET or POST for all 
the operations, which is of course wrong wrt REST. The revision allows you 
to specify the HTTP verb on a per operation basis. Philippe will post this 
soon. Pls comment on that when it appears.

SOAP 1.2 only specifies GET and POST, not the other HTTP verbs, allow it 
leaves this possibility open. I think there is value is using the other 
verbs but I personally could use some guidance on their semantics. For 
example, to create a new Part at Part Depot, what should I do? Should I 
POST a Part document to the part list URI, or should I PUT a Part document 
to a new part URI? Also, technically, a purist might say that my Update 
Quantity example was a hack since I should really PUT and new Part 
document (or subset of one) to the Part URI instead of POSTing. When I 
DELETE, am I deleting from the Part List URI or do I send a DELETE to the 
Part URI? I think we could make progress on the other verbs if there was a 
shared understanding of their intended semantics. At present, we have at 
least established that GET should be side-effect free to enable caching. 
Perhaps we could adopt the semantics for the verbs defined by WebDAV?

I understand the point about uniform interface, and I think we are not 
really inconsistent here. In my example below, I call the operation 
getPartDetail, but that is really just documentation for the reader. That 
verb does NOT appear on the URI. Consider queries we might make on the 
part list. If I do an unqualified GET, I receive the entire state of the 
list. But maybe if the list if huge, the server will rightly refuse to 
send it, and instead sends me a failure response. What I should do is a 
GET that filters the result by some criteria. For example, I could define 
a getByIdRange operation in WSDL like this:

<message name="getByIdRangeInput">
        <part name="lowerId" type="xsd:string"/>
        <part name="upperId" type="xsd:string"/>
</message>

<portType name="partDetailInterface">
        <operation name="getByIdRange">
                <input message="tns:getByIdRangeInput"/>
                <output message="tns:getPartListOutput"/>
        </operation>
        ....
</portType>

I invoke the operation like:

http://www.part-depot.com/parts?lowerId=00300&upperId=00500

So we are still using the GET verb, but we are documenting the semantics 
of the query parameters in the WSDL and giving the operation a meaningful 
name. If this was Smalltalk, the operation would be named something like 
GET:lowerId:upperId, i.e. the formal parameter names get concatenated 
together to form a method name. GET is like an overloaded method in C++, 
Java, etc. The unfiltered and filtered operations have the following 
signatures:

PartList GET( );
PartList GET(String lowerId, String upperId);

In WSDL we decided to avoid overloading, so we need to assign unique names 
to the operations. For HTTP, the names don't necessarily appear in the 
message. However, the names are still useful when it comes to code 
generation, e.g. the above operations get mapped to:

PartList getPartList( );
PartList getByIdRange(String lowerId, String upperId);

So circling back to your suggestion, I think it would be useful to add 
information to the operation to indicated its semantics (e.g. 
create/delete/update/retrieve, aka CRUD), but this is independent of HTTP 
since the operation definition is abstract. The semantic hint could be 
used to select the proper HTTP verb in the HTTP binding and the SOAP/HTTP 
binding. For example, delete/create/update might collapse unto POST for 
SOAP/HTTP.

Arthur Ryman




"Mark Baker" <mbaker@idokorro.com>
Sent by: www-ws-desc-request@w3.org
03/27/2003 02:23 PM

 
        To:     "Arthur Ryman" <ryman@ca.ibm.com>, <www-ws-desc@w3.org>
        cc: 
        Subject:        RE: Thoughts on urlReplacement, REST, and R085

 


Right on, Arthur.
 
I just have one minor disagreement with it though, where you say that
you believe that satisfying R085 will suffice to address this
deficiency.  While I believe that satisfying R085 is necessary, I don't
believe it is sufficient, as I also believe that issue 64 must be
addressed, perhaps with a solution that I proposed in [1] and [2].  The
reason I believe this, is that the semantics of a WSDL operation (e.g.
"getPartDetail" in the example you provided) is no longer part of the
interface published by the server when GET is used (i.e. clients aren't
required to know what it means).  So just satisfying R085 would leave
WSDL in a state where sometimes operation names are part of the
interface, and sometimes not.  My proposal to expose GET, PUT, POST,
etc.. as WSDL operation names would address this.
 
Does that make sense?
 
Thanks.
 
BTW, apologies in advance for future tardy followups, as I'm only able
to get email sporadically while I endure the painful process of
switching ISPs. 8-{
 
 [1] http://lists.w3.org/Archives/Public/www-ws-desc/2003Jan/0103
<http://lists.w3.org/Archives/Public/www-ws-desc/2003Jan/0103> 
 [2] http://lists.w3.org/Archives/Public/www-ws-desc/2003Jan/0111
<http://lists.w3.org/Archives/Public/www-ws-desc/2003Jan/0111> 
 
MB

-----Original Message-----
From: Arthur Ryman [mailto:ryman@ca.ibm.com]
Sent: Thursday, March 27, 2003 10:50 AM
To: www-ws-desc@w3.org
Subject: Thoughts on urlReplacement, REST, and R085



I took an action item on 2003-02-13 to look at urlReplacement and to
determine if it was adequate for REST style Web services. My conclusion
is that urlReplacement is syntactically expressive enough to describe
the type of URIs employed, but its use raises architectural concerns.
Consider the example described in "Building Web Services the REST Way"
by  Roger L. Costello [1]. 

In this example, there is a Web application at the fictious company
"Parts Depot, Inc." that allows you to obtain a list of parts, get
detailed information about a specific part, and submit a purchase order
. 


To obtain the part list, send an HTTP GET to: 


http://www.parts-depot.com/parts 


You receive the following XML document: 


<?xml version="1.0"?> 
<p:Parts xmlns:p="http://www.parts-depot.com" 
         xmlns:xlink="http://www.w3.org/1999/xlink"> 
      <Part id="00345"
xlink:href="http://www.parts-depot.com/parts/00345"/> 
      <Part id="00346"
xlink:href="http://www.parts-depot.com/parts/00346"/> 
      <Part id="00347"
xlink:href="http://www.parts-depot.com/parts/00347"/> 
      <Part id="00348"
xlink:href="http://www.parts-depot.com/parts/00348"/> 
</p:Parts> 

To obtain the detail on part 00345, send an HTTP GET: 


http://www.parts-depot.com/parts/00345 

You receive the following XML document: 

<?xml version="1.0"?> 
<p:Part xmlns:p="http://www.parts-depot.com" 
        xmlns:xlink="http://www.w3.org/1999/xlink"> 
      <Part-ID>00345</Part-ID> 
      <Name>Widget-A</Name> 
      <Description>This part is used within the frap
assembly</Description> 
      <Specification
xlink:href="http://www.parts-depot.com/parts/00345/specification"/> 
      <UnitCost currency="USD">0.10</UnitCost> 
      <Quantity>10</Quantity> 
</p:Part> 

In this example we have 5 URI's: 1 for the part list and 4 for the
parts. How many Web services do we have? In [1] the view is that we have
two, one for the part list and one for all the parts. 

Consider the part detail service. If we only have the GET operation
described here, then WSDL 1.1 urlReplacement is adequate to describe the
service., e.g. 

<message name="partDetailInput"> 
        <part name="id" type="xsd:string"/> 
<message/> 

<message name=partDetailOutput"> 
        <part name="return" element="tns:PartDetail"/> 
</message> 

<portType name="partDetailInterface"> 
        <operation name="getPartDetail"> 
                <input message="tns:partDetailInput"/> 
                <output message="tns:partDetailOutput"/> 
        </operation> 
</portType> 

<binding name="partDetailHttp" type="tns:partDetailInterface"> 
        <http:binding verb="GET"/> 
        <operation name="getPartDetail"> 
                <http:operation location="(id)"/> 
                <input> 
                        <http:urlReplacement/> 
                </input> 
                <output> 
                        <mime:mimeXml part="return"/> 
                </output> 
        </operation> 
</binding> 

<service name="partDetailService"> 
        <port name="partDetailPort" binding="tns:partDetailHttp> 
                <http:address
location="http://www.part-depot.com/parts/"/> 
        </port> 
</service> 

However, this approach breaks down if we add another operation, say one
to update the part detail, using POST. Although we can't combine GET and
POST in the same binding in WSDL 1.1, this is an accepted requirement
for WSDL 1.2. Let's assume we have an updateQuantity operation which has
the following input message: 

<message name="updateQuantityInput"> 
        <part name=id" type=xsd:string"/> 
        <part name="quantity" type="xsd:int"/> 
</message> 

We have a problem now because we need to bind the id to the url using
urlReplacement and the quantity to the message body using mimeXml. But
urlReplacement and mimeXml are mutually exclusive in WSDL 1.1. We could
simply revise the binding in WSDL 1.2 to allow this, but then we run
into another conceptual problem. 

Consider the output of the part list. It contains URIs for the parts,
e.g. http://www.part-depot.com/parts/00345. This URI is something we can
send messages to and get responses back from so it is natural to regard
it as the endpoint of a Web service. But in our example we are not
treating each part as a Web service. We are treating the set of all the
parts as a single Web service, i.e. the part detail Web service. 

I suggest that it is natural to regard each part as a Web service
endpoint. The part id is then encoded in the address of the Web service
and is not treated as an input parameter to a Web service operation. We
therefore have one Web service for the part list and one Web service for
each part. Now it is of course non-sensical to have a WSDL <service>
element for each part since the set of parts is more likely to be 40,000
than 4. In practice, the part list would be dynamic with parts being
added and removed. Therefore there must be another way to publish the
URIs for the parts. The answer is in improving the description of the
part list service to include the information that identifies the URIs
are being Web service endpoints. This is requirement R085. A client of
the part detail Web service discovers the part URIs via the part list
Web service, and not via <service> elements in WSDL documents. 

In conclusion, the current urlReplacement mechanism is inadequate in
practice and is inconsistent with REST since it obscures the role of
URIs. IMHO, the correct resolution of this problem lies in satisfying
R085. 

[1] http://www.xfront.com/REST-Web-Services.html

Arthur Ryman

Received on Thursday, 27 March 2003 18:08:37 UTC