In a RESTful web application design, you typically first identify the resources in your application, the nouns. For example, imagine you're writing a library app., and you're working on adding items to a catalogue. So you've got catalogues and items as your nouns.
You then decide to implement the operations on items, which live in the catalogue. In REST, HTTP verbs map onto the operations you want to perform: POST = create a new resource when you don't know what its identifier should be; PUT = update; DELETE = delete; GET = query resources. So you might end up with:
| HTTP request | Operation performed on resource | Returns |
|---|---|---|
| GET /catalogue/items?term=potter | Retrieve items containing the term "potter" | Representation of items, with a 200 OK status code |
| POST /catalogue/items Request body contains representation of new item | Add a new item to the catalogue | 201 Created status code, with Location header set to URI of new resource, and representation of resource in response body |
| PUT /catalogue/items/<control number> Request body contains representation of updated item | Replace existing representation with an updated one | 200 OK status code |
| DELETE /catalogue/items/<control number> | Remove item at the specified location | 204 No Content status code |
Fairly typical REST.
Then you realise you want to upload a whole pile of items at once, embedded in a single request for efficiency; but you don't want the client to have to wait while the items are inserted into the catalogue and properly indexed etc.. Maybe it will take 5 minutes or something, and you don't want to leave a web client hanging. Or perhaps you want to upload only a single item, but once items are uploaded they are put into a queue for processing by another system, so there's a wait.
What are your choices? Here are some ideas, partly gleaned from the RESTful Web Services book:
However, what I'm not so keen on is the idea of a job or service being a resource. Why? Well, if I want to create items in my catalog, I don't want to wrap them in a job and post them to /jobs; if I want to query my items, I don't want to have to go to a query service at /services/query or similar.
What these paths hint at to me is that an operation is being represented by that path, rather than a resource: effectively, calling them is like doing RPC: you pass the resources you want to act on as arguments to the procedure you're calling. Often, there's also some implicit resource hidden away behind the job or service. Compare:
Or:
It's kind of like the difference between object-oriented design (REST) and procedural design (RPC). While a job might look like a resource, my opinion is that it's really an amorphous wrapper around the real resource you should be representing. Typically, jobs get introduced to cope with asynchronous updates; I'd prefer to see asynchronous operations occurring on proper resources, but exposed using the batch processing approaches outlined above. Otherwise I fear you might lose your resources inside some vague blob of a "job" or "service".
Comments
How is REST similar to object-orientation?
Would an OOP developer constrain themselves to a meager handful of methods, only get/set/delete? Of course not, you would code into your classes whatever verbs, actions or methods are required by the given application. That is the principal shortcoming of REST: in the web development sphere, it has been bound to the methods of a single protocol, HTTP, and as such it inherits HTTP's limitations.
RPC over HTTP doesn't share that limitation, you may define and implement any verb required by the application, in this case a batch of requests. Why not send a POST body of RESTful URIs, and get back a multi-part response or something similar?
REST and RPC both have their advantages. REST is simple to implement, RPC less so. RPC is unaffected by whatever transport layer it travels over; not the case with REST. So use both, judiciously! Don't box yourself in.
And don't pit them against each other, that's holy war turf, unnecessary. As web application complexities increase, remaining flexible about data messaging will broaden your solution space.
I agree, Kevin: I often feel
I agree, Kevin: I often feel constrained by REST's meagre handful of verbs, and have trouble mapping certain operations. The comparison I was trying to make was between having resources which know how to respond to verbs (like objects) vs. services which act on resources (like procedures). I would definitely consider RPC-style web applications if I felt they were necessary. I wasn't trying to pit them head to head in a death match; just interested in the way they focus the mind on different aspects of the design. I suppose ideally what I'd want would be remote object calls (ROC). Though I believe that's what Java RMI and Corba are for, isn't it...?