<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jason R Briggs &#187; transactions</title>
	<atom:link href="http://www.briggs.net.nz/log/tag/transactions/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.briggs.net.nz/log</link>
	<description>Techie stuff from the perspective of a Kiwi abroad</description>
	<lastBuildDate>Mon, 28 Jun 2010 06:45:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Units of Work</title>
		<link>http://www.briggs.net.nz/log/2009/03/20/units-of-work/</link>
		<comments>http://www.briggs.net.nz/log/2009/03/20/units-of-work/#comments</comments>
		<pubDate>Fri, 20 Mar 2009 22:59:26 +0000</pubDate>
		<dc:creator>jrbriggs</dc:creator>
				<category><![CDATA[commentary]]></category>
		<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[distributed]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[transactions]]></category>

		<guid isPermaLink="false">http://www.briggs.net.nz/log/?p=666</guid>
		<description><![CDATA[In regard to cross-resource transactions, I&#8217;m a member of the camp that wonders whether distributed transactions are strictly necessary in the REST/HTTP world; indeed I wonder whether they represent a design failure in modeling the granularity of your resources. That said, we don&#8217;t live in a perfect world &#8212; and even if I can&#8217;t envisage [...]]]></description>
			<content:encoded><![CDATA[<p>In regard to <a href="http://www.jboss.org/community/docs/DOC-13311">cross-resource transactions</a>, I&#8217;m a member of the <a href="http://www.innoq.com/blog/st/2009/03/restful_transactions.html">camp</a> that wonders whether distributed transactions are strictly necessary in the REST/HTTP world; indeed I wonder whether they represent a design failure in modeling the granularity of your <a href="http://rest.blueoxen.net/cgi-bin/wiki.pl?RestResources">resources</a>.</p>
<p>That said, we don&#8217;t live in a perfect world &#8212; and even if I can&#8217;t envisage why a properly designed RESTful application might require access to a distributed transaction, I can certainly envisage the environment where such an application might evolve.  I&#8217;ve worked in a few of them.  Places where interdepartmental barriers are as solid as the Great Wall; bastions of archaic technology where <em>&#8220;one might provide a pseudo-RESTful interface, but one certainly won&#8217;t be re-architecting one&#8217;s legacy system in the buzzword language of the day&#8221;</em>. </p>
<p>But, I think there&#8217;s a certain amount of smoke and mirrors in the JBossTS article &#8220;<a href="http://www.jboss.org/community/docs/DOC-13311">Transactional support for JAX RS based applications</a>&#8220;:</p>
<p><em>Certainly it is worth pointing out that if a system cannot be made reliable then it can be of only limited utility. That said it is a worthwhile exercise to show how a REST based system can be made reliable. </em></p>
<p>Lack of distributed transactions would hardly seem to make a REST based system &#8220;unreliable&#8221; and, as a consequence, of &#8220;only limited utility&#8221;.  Imagine a hotel booking facility &#8212; perhaps a <em>booking</em> resource, which internally might be constructed from a number of components, all governed (again internally) by transaction demarcation.  Does the fact that the booking resource is coarse-grained and does not require an external transaction make it less reliable than a number of fine-grained resources which do?  On the contrary. The latter sounds more like a WS-* api than a RESTful architecture, nothing to do with reliability.</p>
<p>So&#8230; hopefully it&#8217;s obvious I think it&#8217;s a bad idea.  But if I <strong>were</strong> to write such an API, I think the 8-year old spec mentioned in the article falls short of the mark.  Here&#8217;s my first-cut attempt at an alternative (which I still think falls a bit short of the mark, but is possibly an improvement):</p>
<table>
<tr>
<th colspan="5">Resource: tc</th>
</tr>
<tr>
<th>Method</th>
<th>URL</th>
<th>Content</th>
<th>Description</th>
<th>Statuses</th>
</tr>
<tr>
<td>GET</td>
<td>/tc</td>
<td></td>
<td>Returns HTML containing a summary of all transactions (status), plus an href to the transaction detail</td>
<td>200 &#8211; ok</td>
</tr>
<tr>
<td></td>
<td>/tc/{txid}</td>
<td></td>
<td>Returns HTML containing detail for the transaction with id {txid}, including the status and a list of hrefs to the each of the participants. For example:</p>
<pre><code>
&lt;html&gt;
&lt;body&gt;
	&lt;dl&gt;
		&lt;dt&gt;Transaction ID&lt;/dt&gt;
			&lt;dd id="transaction-id"&gt;12345a&lt;/dd&gt;
		&lt;dt&gt;Status&lt;/dt&gt;
			&lt;dd id="transaction-status"&gt;ACTIVE&lt;/dd&gt;
		&lt;dt&gt;Timeout&lt;/dt&gt;
			&lt;dd id="transaction-timeout"&gt;5000&lt;/dd&gt;
	&lt;/dl&gt;
	&lt;ul id="participants"&gt;
		&lt;li&gt;
			&lt;a href="/tc/12345a/participants/1"&gt;
				Participant 1
			&lt;/a&gt;
		&lt;/li&gt;
		&lt;li&gt;
			&lt;a href="/tc/12345a/participants/2"&gt;
				Order
			&lt;/a&gt;
		&lt;/li&gt;
	&lt;ul&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
</td>
<td>200 &#8211; ok<br/><br />
404 &#8211; if txid is not found<br />
409 &#8211; if the transaction has been deleted</td>
</tr>
<tr>
<td></td>
<td>/tc?status={status-type}</td>
<td></td>
<td>Return HTML containing a summary of transactions with a specific status, with href to the transaction detail<br />
For example: /tc?status=recovering or /tc?status=active</td>
<td>200 &#8211; ok</td>
</tr>
<tr>
<td></td>
<td>/tc/{txid}/participants</td>
<td></td>
<td>Return a list of participants in the transaction (list of hrefs)</td>
<td>200 &#8211; ok<br />
404 &#8211; if the transaction does not exist</td>
</tr>
<tr>
<td></td>
<td>/tc/{txid}/partipants/{rec-coord-id}</td>
<td></td>
<td>Return HTML containing the detail of a participant.  For example:</p>
<pre><code>
&lt;html&gt;
&lt;title&gt;Participant #2&lt;/title&gt;
&lt;body&gt;
&lt;dl&gt;
    &lt;dt&gt;ID&lt;/dt&gt;
        &lt;dd&gt;2&lt;/dd&gt;
    &lt;dt&gt;Name&lt;/dt&gt;
        &lt;dd&gt;Order&lt;/dd&gt;
    &lt;dt&gt;URL&lt;/dt&gt;
        &lt;dd&gt;
            &lt;a href="http://internal.mydomain.com/someresource/123"&gt;Order&lt;/a&gt;
        &lt;/dd&gt;
&lt;/dl&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
</td>
<td>200 &#8211; ok<br />
404 &#8211; if the transaction or participant does not exist</td>
</tr>
<tr>
<td>POST</td>
<td>/tc</td>
<td>[timeout={timeout}]</td>
<td>Start a transaction (with default timeout) returning the url /tc/{txid} &#8212; which is deleted after the timeout or after completion (any HTTP method relating to {txid} thereafter returns 404). Use timeout={timeout} to override the default timeout period.</td>
<td>201 &#8211; created</td>
</tr>
<tr>
<td>DELETE</td>
<td>/tc/{txid}</td>
<td></td>
<td>Rollback and stop a transaction</td>
<td>204 &#8211; ok<br />
404 &#8211; if the transaction does not exist</td>
</tr>
<tr>
<td></td>
<td>/tc/{txid}?commit</td>
<td></td>
<td>Commit and stop a transaction</td>
<td>204 &#8211; ok<br />
404 &#8211; if the transaction does not exist</td>
</tr>
<tr>
<td>POST</td>
<td>/tc/{txid}/participants</td>
<td>url={url}&#038;[name={name}]</td>
<td>Enlist {url} in the transaction, returning a unique resource for that participant of the form /tc/{txid}/participants/{rec-coord-id}. If name exists, record against the participant detail</td>
<td>201 &#8211; created<br />
404 &#8211; if the transaction does not exist</td>
</tr>
<tr>
<td>PUT</td>
<td>/tc/{txid}/participants/{rec-coord-id}</td>
<td>url={url}</td>
<td>Replace the participant url</td>
<td>200 &#8211; ok<br />
404 &#8211; if the transaction or participant does not exist</td>
</tr>
</table>
<p>The resource identified by a participant URL will have the following semantics:</p>
<table>
<tr>
<th>Method</th>
<th>URL</th>
<th>Content</th>
<th>Description</th>
<th>Statuses</th>
</tr>
<tr>
<td>PUT</td>
<td>URL/tx/{rec-coord-id}</td>
<td>action=prepare</td>
<td>The participant prepares any work done in the context of the transaction. The Warning header will contain additional info about the state of the prepare (either readonly, or notok).</td>
<td>200 &#8211; ok<br />
200 &#8211; ok (+ Warning: readonly)<br />
200 &#8211; ok (+ Warning: notok)<br />
404 &#8211; participant has rolled back</td>
</tr>
<tr>
<td></td>
<td></td>
<td>action=commit</td>
<td>The participant commits any work done in the context of the transaction.</td>
<td>200 &#8211; ok<br />
200 &#8211; ok (+ Warning: heuristic)<br />
404 &#8211; participant has rolled back</td>
</tr>
<tr>
<td></td>
<td></td>
<td>action=rollback</td>
<td>The participant commits any work done in the context of the transaction.</td>
<td>200 &#8211; ok<br />
200 &#8211; ok (+ Warning: heuristic)<br />
404 &#8211; participant has already rolled back</td>
</tr>
</table>
<p>Basic usage might look something like the following:</p>
<table>
<tr>
<td colspan="2">1. Create a new transaction resource</td>
</tr>
<tr>
<td>
<pre><code>POST /tc
Host: somedomain.com

timeout=5000
</code></pre>
</td>
<td>
<pre><code>HTTP/1.1 201 Created
Connection: close
Date: Thu, 19 Mar 2009 21:01:56 GMT
Location: http://somedomain.com/tc/10a23v991
X-Powered-By: TransactionServer/0.1
</code></pre>
</td>
</tr>
<tr>
<td colspan="2">2. Create a new resource of some kind (notify the resource that it will operate with a distributed transaction)</td>
</tr>
<tr>
<td>
<pre><code>POST /res1?tx
Host: internaldept1.somedomain.com

&lt;xml&gt;some xml describing the resource&lt;/xml&gt;
</code></pre>
</td>
<td>
<pre><code>HTTP1.1 201 Created
Connection: close
Date: Thu, 19 Mar 2009 21:01:56 GMT
Location: http://internaldept1.somedomain.com/res1/100
</code></pre>
</td>
</tr>
<tr>
<td colspan="2">3. Update another resource (again notify that it will be operating within a transaction)</td>
</tr>
<tr>
<td>
<pre><code>PUT /res2/somename?tx
Host: internaldept2.somedomain.com

&lt;xml&gt;some xml describing the update,
perhaps including a reference to the previously
created resource&lt;/xml&gt;
</code></pre>
</td>
<td>
<pre><code>HTTP1.1 200 Ok
Connection: close
Date: Thu, 19 Mar 2009 21:01:56 GMT
Location: http://internaldept2.somedomain.com/res2/somename
</code></pre>
</td>
</tr>
<tr>
<td colspan="2">4. Enlist the url for each resource in the transaction</td>
</tr>
<tr>
<td>
<pre><code>POST /tc/10a23v991/participants
Host: somedomain.com

name=resource1&amp;url=http://internaldept1.somedomain.com/res1/100
</code></pre>
</td>
<td>
<pre><code>HTTP/1.1 201 Created
Connection: close
Date: Thu, 19 Mar 2009 21:01:56 GMT
Location: http://somedomain.com/tc/10a23v991/participants/a01abgv21
X-Powered-By: TransactionServer/0.1
</code></pre>
</td>
</tr>
<tr>
<td>
<pre><code>POST /tc/10a23v991/participants
Host: somedomain.com

name=resource2&amp;url=http://internaldept2.somedomain.com/res2/somename
</code></pre>
</td>
<td>
<pre><code>HTTP/1.1 201 Created
Connection: close
Date: Thu, 19 Mar 2009 21:01:56 GMT
Location: http://somedomain.com/tc/10a23v991/participants/a01abgv22
X-Powered-By: TransactionServer/0.1
</code></pre>
</td>
</tr>
<tr>
<td colspan="2">5. Commit the transaction</td>
</tr>
<tr>
<td>
<pre><code>DELETE /tc/10a23v991?action=commit
Host: somedomain.com
</code></pre>
</td>
<td>
<pre><code>HTTP/1.1 204 Committed and deleted
Connection: close
Date: Thu, 19 Mar 2009 21:01:56 GMT
X-Powered-By: TransactionServer/0.1
</code></pre>
</td>
</tr>
<tr>
<td colspan="2">6. &#8216;Behind the scenes&#8217;, the commit results in the following (2-phase commit at this point)&#8230;</td>
</tr>
<tr>
<td>
<pre><code>PUT /res1/100/tx/a01abgv21
Host: internaldept1.somedomain.com

action=prepare
</code></pre>
<pre><code>PUT /res2/somename/tx/a01abgv22
Host: internaldept2.somedomain.com

action=prepare
</code></pre>
<p>and</p>
<pre><code>PUT /res1/100/tx/a01abgv21
Host: internaldept1.somedomain.com

action=commit
</code></pre>
<pre><code>PUT /res2/somename/tx/a01abgv22
Host: internaldept2.somedomain.com

action=commit
</code></pre>
</td>
<td></td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.briggs.net.nz/log/2009/03/20/units-of-work/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
