<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xml:base="http://townx.org" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
 <title>townx - Are &amp;quot;jobs&amp;quot; just disguised RPC in a RESTful application? - Comments</title>
 <link>http://townx.org/blog/elliot/are-jobs-just-disguised-rpc-restful-application</link>
 <description>Comments for &quot;Are &quot;jobs&quot; just disguised RPC in a RESTful application?&quot;</description>
 <language>en</language>
<item>
 <title>Are &quot;jobs&quot; just disguised RPC in a RESTful application?</title>
 <link>http://townx.org/blog/elliot/are-jobs-just-disguised-rpc-restful-application</link>
 <description>&lt;p&gt;In a &lt;a href=&quot;http://en.wikipedia.org/wiki/RESTful&quot;&gt;&lt;span class=&quot;caps&quot;&gt;REST&lt;/span&gt;ful&lt;/a&gt; web application design, you typically first identify the resources in your application, the nouns. For example, imagine you&#039;re writing a library app., and you&#039;re working on adding items to a catalogue. So you&#039;ve got &lt;strong&gt;catalogues&lt;/strong&gt; and &lt;strong&gt;items&lt;/strong&gt; as your nouns.&lt;/p&gt;

&lt;p&gt;You then decide to implement the operations on items, which live in the catalogue. In &lt;span class=&quot;caps&quot;&gt;REST, HTTP &lt;/span&gt;verbs map onto the operations you want to perform: &lt;span class=&quot;caps&quot;&gt;POST &lt;/span&gt;= create a new resource when you don&#039;t know what its identifier should be; &lt;span class=&quot;caps&quot;&gt;PUT &lt;/span&gt;= update; &lt;span class=&quot;caps&quot;&gt;DELETE &lt;/span&gt;= delete; &lt;span class=&quot;caps&quot;&gt;GET &lt;/span&gt;= query resources. So you might end up with:&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;&lt;th&gt;&lt;span class=&quot;caps&quot;&gt;HTTP &lt;/span&gt;request&lt;/th&gt;&lt;th&gt;Operation performed on resource&lt;/th&gt;&lt;th&gt;Returns&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class=&quot;caps&quot;&gt;GET &lt;/span&gt;/catalogue/items?term=potter&lt;/td&gt;&lt;td&gt;Retrieve items containing the term &quot;potter&quot;&lt;/td&gt;&lt;td&gt;Representation of items, with a 200 OK status code&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class=&quot;caps&quot;&gt;POST &lt;/span&gt;/catalogue/items&lt;br/&gt;Request body contains representation of new item&lt;/td&gt;&lt;td&gt;Add a new item to the catalogue&lt;/td&gt;&lt;td&gt;201 Created status code, with Location header set to &lt;span class=&quot;caps&quot;&gt;URI &lt;/span&gt;of new resource, and representation of resource in response body&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class=&quot;caps&quot;&gt;PUT &lt;/span&gt;/catalogue/items/&amp;lt;control number&amp;gt;&lt;br/&gt;Request body contains representation of updated item&lt;/td&gt;&lt;td&gt;Replace existing representation with an updated one&lt;/td&gt;&lt;td&gt;200 OK status code&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span class=&quot;caps&quot;&gt;DELETE &lt;/span&gt;/catalogue/items/&amp;lt;control number&amp;gt;&lt;/td&gt;&lt;td&gt;Remove item at the specified location&lt;/td&gt;&lt;td&gt;204 No Content status code&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Fairly typical &lt;span class=&quot;caps&quot;&gt;REST.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Then you realise you want to upload a whole pile of items at once, embedded in a single request for efficiency; but you don&#039;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&#039;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&#039;s a wait.&lt;/p&gt;

&lt;p&gt;What are your choices? Here are some ideas, partly gleaned from the &lt;span class=&quot;caps&quot;&gt;REST&lt;/span&gt;ful Web Services book:&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt;Don&#039;t allow bulk uploads. You can only upload one item at a time, and you just have to wait until the operation completes and you get your proper status code back. Not really a solution, though.&lt;/li&gt;
&lt;li&gt;Allow bulk uploads, process the items, and return a multi-status 207 code with the response. You still have to wait for all the processing to finish, but the response body contains a list of response codes and status reports, one for each uploaded item. Again, you have to wait for the upload to finish before you can return anything.&lt;/li&gt;
&lt;li&gt;Allow a bulk upload, but return a 202 Accepted status, spawning asynchronous jobs to do the processing in the background. The response body can contain the &lt;span class=&quot;caps&quot;&gt;URI&lt;/span&gt;s for each uploaded item. Each item then has a status which can be queried by asking for the resource again. For example, when an item is first uploaded, you get its &lt;span class=&quot;caps&quot;&gt;URI &lt;/span&gt;back as a Location; when you &lt;span class=&quot;caps&quot;&gt;GET &lt;/span&gt;that, the object has its status set to &lt;strong&gt;Inactive&lt;/strong&gt; or &lt;strong&gt;Under processing&lt;/strong&gt; or something. When processing is complete, you get a status like &lt;strong&gt;Complete&lt;/strong&gt; on the item instead. The down-side is that your resource representations are polluted with status information, which could be good or bad.&lt;/li&gt;
&lt;li&gt;As above, but your request to /catalogue/items returns a 202 along with a handle to a &quot;transaction&quot; or &quot;job&quot; resource which wraps the resources you uploaded. Effectively, you treat the upload itself as a resource with a status you can query; the resources attached to that resource don&#039;t have to be polluted with status information, but you perhaps lose the granularity of individual status codes on resources. Or maybe you produce one transaction resource per uploaded resource?&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;However, what I&#039;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&#039;t want to wrap them in a job and post them to /jobs; if I want to query my items, I don&#039;t want to have to go to a query service at /services/query or similar.&lt;/p&gt;

&lt;p&gt;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 &lt;span class=&quot;caps&quot;&gt;RPC&lt;/span&gt;: you pass the resources you want to act on as arguments to the procedure you&#039;re calling. Often, there&#039;s also some implicit resource hidden away behind the job or service. Compare:&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt;&lt;span class=&quot;caps&quot;&gt;GET &lt;/span&gt;/catalog/items?term=potter: the catalogue is visible, and we know we&#039;re querying items within it&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;caps&quot;&gt;GET &lt;/span&gt;/services/query?term=potter: here there&#039;s an implicit catalogue and its items behind the service; effectively, these objects are passed invisibly to the procedure we&#039;re calling; also what we&#039;re querying is not explicit&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Or:&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt;&lt;span class=&quot;caps&quot;&gt;POST &lt;/span&gt;/catalog/items: we&#039;re appending a new item to the catalogue; we can infer that our new item will then be available at /catalog/items/&amp;lt;some identifier&amp;gt;&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;caps&quot;&gt;POST &lt;/span&gt;/jobs: job is an amorphous category, and we could post pretty much any type of resource into it; and there aren&#039;t any hints from the &lt;span class=&quot;caps&quot;&gt;API &lt;/span&gt;about how to get at those resources once we&#039;ve posted them&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;It&#039;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&#039;s really an amorphous wrapper around the real resource you should be representing. Typically, jobs get introduced to cope with asynchronous updates; I&#039;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 &quot;job&quot; or &quot;service&quot;.&lt;/p&gt;</description>
 <comments>http://townx.org/blog/elliot/are-jobs-just-disguised-rpc-restful-application#comments</comments>
 <category domain="http://townx.org/tech">tech</category>
 <pubDate>Thu, 20 Mar 2008 16:32:17 -0500</pubDate>
 <dc:creator>elliot</dc:creator>
 <guid isPermaLink="false">709 at http://townx.org</guid>
</item>
</channel>
</rss>
