DELETE and 201 Created

March 7th, 2010

Just thought about a useful combination of DELETE and a 201 Created response:

DELETE /service/documents/667
 
201 Created
Location: /service/archive/documents/667
Content-Type: text/plain
 
Document /service/documents/667 has been deleted
and archived at /service/archive/documents/667.

The Farmer in the Dell

March 2nd, 2010

A couple of minutes ago, Bob Haugen posted a question on the rest-discuss list that essentially comes down to the question of how the use of REST affects a classic 2PC scenario. Note that the question is not how you do 2PC with REST but what the implications are regarding compensation strategies etc.

The scenarios is this: There are N farmers that each have an amount of Xn pints of berries to sell. The farmers tell M market places about their amount and K buyers order berries from the market places. The 2PC issues come in when orders to different market places overlap and more berries are ordered from a farmer than he has available.

I tink this relates very nicely to my RESTifying Procurement endeavor and I therefore plan to make the scenario the overall target to which my experiment should evolve.

Classifying the CouchDB API

February 27th, 2010

In the context of my Classification of HTTP-based APIs @hanonymity today asked me, how I would classify the CouchDB API.

Ok, let’s see. Going to the HTTP Document API immediately reveals that the API definitely violates the hypermedia constraint (see last paragraph) because there is an API documentation in the first place. The only thing one would expect to see for a RESTful API is a set of media type specifications along the lines “The CouchDB API uses the following media types and link relations….which are specified here…”.

Next, let’s check if the API can be classified as HTTP-based Type II. The fastest way to verify this is usually to look for the use of only specified media types and it is immediately obvious that the CouchDB uses the generic media type application/json and not a specific one that would make the messages self-descriptive. CouchDB API fails the test for HTTP-based Type II, too.

This leaves us with the question whether the API is HTTP-based Type I or if we have to let go all hope because it must be classified as RPC URI-Tunneling. The thing to look out for is of course the use of action names in URIs. It does not take a lot of browsing through the API documentation to reveal that the CouchDB API designers knew what they were doing. The API very thoroughly leverages HTTP mechanics and we can happily conclude that the API is an HTTP-based Type I API.

Is it a problem that the CouchDB API violates two out of four of REST’s interface constraints and is therefore not REST at all? I do not think so, because I would not consider achieving loose coupling between a database (backend) and the component that uses the database to be a very useful goal. At least not at the cost that you have to pay on the client side and also because there is strong coupling around the schema anyway between a database and the code that is using it.

However, I think CouchDB API shows quite nicely how an API can still benefit from the simplicity induced by HTTP-based Type I even if we cannot label the API as REST.

A note on the COPY method: It would be helpful to say in the API documentation that the COPY extension method is actually WebDAV’s COPY method. And while we are at it, it makes also sense to note that COPY does not really fit HTTP because COPY is a method that works on two resources (Source and Destination) while HTTP does not support such method semantics. For example, caches would not understand that they need to flush the representations of the (now overwritten) destination resource.

This is not a question of RESTfulness though. It would be entirely possible to design an architecture that adheres to the REST style and provides methods that work on two resources.

Service Types Revisited

February 15th, 2010

Working on the RESTifying Procurement show case I realized that it looks as if I had to revisit my approach towards service types. I have argued that a service type is constituted by the set of hypermedia semantics it makes use of. This seemed reasonable since a client developer needs to know at least a minimal set of the possible hypermedia semantics to expect from a service in order to write a client for a service of that kind.

Unfortunately this approach has some problems when services of different kinds use the same set of hypermedia semantics because the differentiating aspect is lost. I realized this because in the procurement example I am basically using a single media type but still have a range of services, for example supplier or carrier.

A possible solution to this issue is to have the all-encompassing media type define the service types. Such types are still necessary to enable lookup based on type, for example in order to find the carrier service of some external business partner. Looking for the procurement service doesn’t make that much sense.

Markus Karg on the Hypermedia Constraint

February 14th, 2010

As a reaction to the latest experimental proposal for supporting hypermedia in Jersey, Markus chimed in, saying:

If you want to gain all the benefits of REST, you need to apply all four constraints but not just three of them.

I whole-heartedly agree with that.

However, I disagree with his analysis that only the response body (and not the headers) carries the hypermedia that represents the next application state. From a hypermedia constraint point of view it is irrelevant whether the hypermedia controls (that is links, link templates or forms) are placed inside the body or inside the HTTP headers.
Placing the controls into the HTTP header can, for example, be a viable solution when you want to (or have to) use existing document formats for the body that do not provide the ability to place the controls in the body.

Three Aspects of Steady-States

February 13th, 2010

The #rest IRC channel (transcripts here and here) has recently become for me a valuable source for thought stimulation (come and visit). Yesterday we had a discussion regarding steady-states and the following observation has been made:

URIs refer to a certain application state; at least in the sense that one can use a URI to go back to a certain application state or that one can pass a URI to another party to bring this party into that application state.

However, ‘that application state’ (despite the notion that I can use the URI to get back to it) is not stable over time. The semantics of the mapping are, but the transitions available form that state can change. So, what is the significance of ‘that application state’?

I have not figured that out yet, but here is a thought I had this morning as a reaction to the discussion:

A Web application comprises a state machine that can change over time. Each state (aka steady-state) of that state machine has three aspects:

  1. Its semantics (what the state means)
  2. The serialized state of the associated domain concept (e.g. order 10029)
  3. The outgoing transitions to other states

The first of the three is constrained to remain stable over time the other two vary depending on the state of the associated domain concept and the actual state machine the server intends to provide to (that particular) client.

UPDATE: It has come up in a number of places a notion of transient states or ephemeral URIs. As far as I understand the issue circles around the idea of giving distinct URIs to different states of application states. With this approach, an order in some ‘review-pending’ state would be represented by a different resource (and hence different URI) than the same order in the state ’shipment-initiated’. Please correct me, if I miss the point here.

My response to that can be found in this comment on Ian’s blog.

I’d highly apprechiate if someone could shed more light on this issue. I think it is a deep one.

RESTifying Procurement – Service Running

February 12th, 2010

Though not much yet, I have put the procurement service online. At the moment, the service for the supplier party of the UBL business process is provided by the implementation. It can be accessed at http://labs.nordsc.com:8080/rp/supplier/service.

$ curl http://labs.nordsc.com:8080/rp/supplier/service | tidy -xml -i -q
 
<service xmlns="http://www.w3.org/2007/app"
xmlns:atom="http://www.w3.org/2005/Atom">
  <workspace>
    <atom:title type="text">This service implements the UBL
    supplier role.</atom:title>
    <atom:link rel="common-catalogue"
    href="http://labs.nordsc.com:8080/rp/supplier/provider/common-catalogue"
    type="application/procurement+xml;type=catalogue"
    title="The public catalogue"></atom:link>
  </workspace>
</service>

The service document provides a link to the common catalogue provided by the provider role (here played by the supplier party). I explain the special use I make of AtomPub service documents in this post.

A client that understands the ‘common-catalogue’ link relation and intends to look at the common catalogue can now do this:

$ curl http://labs.nordsc.com:8080/rp/supplier/provider/common-catalogue | tidy -xml -i -q
 
<?xml version='1.0' encoding='utf-8'?>
<?xml-stylesheet href='http://labs.nordsc.com:8080/rp/css/catalogue.css' type='text/css'?>
<Catalog xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns="urn:oasis:names:specification:ubl:schema:xsd:Catalogue-2">
  <cbc:ID>public-001</cbc:ID>
  <cbc:IssueDate>2012-02-02</cbc:IssueDate>
  <cac:CatalogueLine>
    <cbc:ID>1</cbc:ID>
    <cac:RequiredItemLocationQuantity>
      <cac:Price>
        <cbc:PriceAmount currencyID="EUR">16.90</cbc:PriceAmount>
      </cac:Price>
    </cac:RequiredItemLocationQuantity>
    <cac:Item>
      <cbc:Name>Valve 1-54</cbc:Name>
      <cbc:Description>This valve helps with a lot of
      things</cbc:Description>
      <cac:SellersItemIdentification>
        <cbc:ID schemeURI="http://labs.nordsc.com/schemes/items/"
        schemeDataURI="http://labs.nordsc.com:8080/rp//provider/items/">
        PARTS-7615221</cbc:ID>
      </cac:SellersItemIdentification>
    </cac:Item>
  </cac:CatalogueLine>
<cac:CatalogueLine>
    <cbc:ID>2</cbc:ID>
    <cac:RequiredItemLocationQuantity>
      <cac:Price>
        <cbc:PriceAmount currencyID="EUR">26.90</cbc:PriceAmount>
      </cac:Price>
    </cac:RequiredItemLocationQuantity>
    <cac:Item>
      <cbc:Name>Valve 2-54</cbc:Name>
      <cbc:Description>This valve helps with a lot of
      things</cbc:Description>
      <cac:SellersItemIdentification>
        <cbc:ID schemeURI="http://labs.nordsc.com/schemes/items/"
        schemeDataURI="http://labs.nordsc.com:8080/rp//provider/items/">
        PARTS-7625222</cbc:ID>
      </cac:SellersItemIdentification>
    </cac:Item>
  </cac:CatalogueLine>
  <cac:CatalogueLine>
    <cbc:ID>3</cbc:ID>
    <cac:RequiredItemLocationQuantity>
      <cac:Price>
        <cbc:PriceAmount currencyID="EUR">36.90</cbc:PriceAmount>
      </cac:Price>
    </cac:RequiredItemLocationQuantity>
    <cac:Item>
      <cbc:Name>Valve 3-54</cbc:Name>
      <cbc:Description>This valve helps with a lot of
      things</cbc:Description>
      <cac:SellersItemIdentification>
        <cbc:ID schemeURI="http://labs.nordsc.com/schemes/items/"
        schemeDataURI="http://labs.nordsc.com:8080/rp//provider/items/">
        PARTS-7635223</cbc:ID>
      </cac:SellersItemIdentification>
    </cac:Item>
  </cac:CatalogueLine>
</Catalog>

According to the to-be-written processing intent of application/procurement+xml a client could now select items from the catalogue and create an order from them. How that order looks and – more interesting – where to send that order will be the subject of one of the next posts.

The implementation will serve the examples as application/xml to browsers thanks to Jersey’s conneg support so you won’t get an annoying download. There is also CSS styling of the XML so you can actually see something.

RESTifying Procurement – The Media Type

February 12th, 2010

In the examples throughout this series I am using (among others) the hypothetical media type application/procurement+xml. In this post I will start fleshing out its specification.

A central aspect of the RESTifying Procurement project is the use of the UBL document family. UBL actually encourages adopters to customize the documents to suit the needs of the interacting parties which usually means specializing upon the very flexible UBL documents types. There are also guidelines for evolving the document types to forward incompatible new types but I’ll rather stick with standard UBL.

UBL has not been build with hypermedia in mind and does not provide explicit linking facilities. In order to address that limitation I’ll define a special processing intent for <cbc:ID> elements, make use of HTTP Link headers and, where appropriate, use hypertext enabled media types such as application/atom+xml.

The hypothetical media type application/procurement+xml encompasses specialized versions of several UBL document types and associates with them a processing model as far as that is necessary to enable the associated business processes to be carried out by software components communicating via HTTP.

The current list of document types (which I will update when new types are added) is shown below. For every document type a value for a type parameter for the media type is provided to enable content negotiation based on the individual document types.

UBL Document type parameter value RelaxNG Schema Example
Catalogue catalogue Catalogue.rnc (xml)
Order order Order.rnc (xml)


Additional Processing Rules for the <cbc:ID> Element
The <cbc:ID> element is used throughout the UBL for identification. Various attributes can be used to identify the schema to which the identifier itself belongs. A common use of the element would be

 
<cbc:ID schemeURI="http://labs.nordsc.com/schemes/products">
  PARTS-7635223</cbc:ID>

Which means that the thing being identified has the identifier PARTS-7635223 and that this identifier is taken from the scheme (namespace) identified by http://labs.nordsc.com/schemes/products. This is similar to Atom’s <category> element that combines a scheme and a term attribute for the same purpose.

Unfortunately, the element does not directly provide for the use of URIs for identification, meaning that one cannot do something like this:

 
<cbc:ID href="http://labs.nordsc.com/repository/items/1234">
  1234</cbc:ID>

That is a strange situation (at least in Web context): UBL provides an element for identification but does not support the use of URIs as identifiers. To solve this, I decided to cheat a little and turn the <cbc:ID> element into a hyperlink.

The <cbc:ID> element provides an attribute named schemeDataURI that enables authors to reference a resource where the scheme data is available (the list of all identifiers and their description).

What if I defined the processing intention of application/procurement+xml to understand the concatenation of the schemeDataURI and the actual identifier to be a URI identifier for the thing identified by the given <cbc:ID> element? Yes, that would enable <cbc:ID> to turn into a hyperlink.

An element such as

 
<cbc:ID schemeURI="http://labs.nordsc.com/schemes/items/"
  schemeDataURI="http://labs.nordsc.com/service/items/">
  PARTS-7635223</cbc:ID>

can then be interpreted as a link referencing http://labs.nordsc.com/service/items/PARTS-7635223.

For now the specification of application/procurement+xml consists of the specialized Catalogue document type and the special processing rule for <cbc:ID> element.

I will update this posting as the media type grows.

More Comments on Jersey

February 10th, 2010

This posting to the Jersey user’s list provides more detailed comments, explaining my concerns.

UPDATE: The thread started by the reference above turned out to be rather interesting. It’s worth a look.

Jersey Going Astray?

February 9th, 2010

Santiago Pericas-Geertsen today wrote about the approach currently taken by Jersey towards providing active server-side support for the hypermedia constraint.

Given the exposure of Jersey I am worried to say the least.

Santiago writes:

It has been identified by other authors that there are actions that cannot be easily mapped to read or write operations on resources.

This quote creates the impression as if there was a problem that needed to be solved and that Jersey will help developers to solve it. This scares me!

It scares me because it looks as if one of the most exposed RESTful HTTP frameworks is about to evolve not on the basis of how to enforce RESTful systems but based on a likely misconception of REST. What we need is to help architects and developers to design RESTful REST systems and not support REST misconceptions by hard coding them into a framework. Apologies if this sounds insulting, I don’t mean to be. I am just worried.

Here is the misconception: with REST, we do not map actions to read or write operations on resources but we achieve coordination between processes by transferring representations. Representations sent from server to client advance the client’s application state and representations that are sent from client to server change resource state. The notions of ‘action’ and ‘read or write’ resources simply do not exist in REST and just because some authors have identified a problem related to these notions should not drive the evolution of JSR311.

In REST a coordination goal is achieved by changing the state of a resource that has the proper semantics. All that is needed is the specification of media types that provide the necessary hypermedia semantics for the client to find such proper resources. RESTful frameworks should encourage the design of proper media types and ideally enforce correct client side behavior instead of introducing a concept of ‘action resources’ that just does not exist in REST.

The primary design artifact for RESTful services is media types, link relations, etc. (there just is nothing else to design) and behind those is very serious and time consuming design work. Pretending that a framework (let alone ‘action resources’) could make this any simpler is misleading.

I guess I have now put myself in a position of having to provide more constructive feedback :-) I’ll give that a try tomorrow.

And apologies again to those people whose work I am criticizing.

UPDATE: Markus Karg chimes in.