<?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/"
	>

<channel>
	<title>DJ's Weblog</title>
	<atom:link href="http://www.pipetree.com/qmacro/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pipetree.com/qmacro/blog</link>
	<description>Reserving the right to be wrong</description>
	<pubDate>Fri, 27 Aug 2010 06:44:19 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Getting started with Gmail Contextual Gadgets</title>
		<link>http://www.pipetree.com/qmacro/blog/2010/06/getting-started-with-gmail-contextual-gadgets/</link>
		<comments>http://www.pipetree.com/qmacro/blog/2010/06/getting-started-with-gmail-contextual-gadgets/#comments</comments>
		<pubDate>Mon, 21 Jun 2010 20:31:10 +0000</pubDate>
		<dc:creator>dj</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[appengine]]></category>

		<category><![CDATA[contextual]]></category>

		<category><![CDATA[dashboard]]></category>

		<category><![CDATA[gadgets]]></category>

		<category><![CDATA[gmail]]></category>

		<guid isPermaLink="false">http://www.pipetree.com/qmacro/blog/?p=803</guid>
		<description><![CDATA[Gmail contextual gadgets were announced by Google a few months back and were made available to developers in May this year, just before making a strong appearance at Google IO.
Expanding upon the concept of an earlier contextual project called Dashboard, Gmail contextual gadgets give a clear message that email, as a universal information carrier and workflow [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.google.com/apis/gmail/gadgets/contextual/">Gmail contextual gadgets</a> were announced by Google a few months back and were <a href="http://googleenterprise.blogspot.com/2010/05/putting-email-in-context-with-gmail.html">made available to developers in May this year</a>, just before making a <a href="http://code.google.com/events/io/2010/sessions/deep-dive-gmail-contextual-gadgets.html">strong appearance at Google IO</a>.</p>
<p>Expanding upon the concept of an earlier contextual project called <a href="http://www.pipetree.com/qmacro/blog/2003/07/dashboard-a-compelling-articulation-for-realtime-contextual-information-2/">Dashboard</a>, Gmail contextual gadgets give a clear message that email, as a universal information carrier and workflow pipeline, is not only here to stay, but is being given a new lease of life as it plays a foundational role in Google&#8217;s enterprise scale application platform strategy. A Gmail contextual gadget enhances email messages by providing information or functionality that is relevant to the context of that email &#8230; right inside the email itself. Context is exposed by content extractors in the form of &#8216;clues&#8217; in Gmail (akin to Dashboard&#8217;s &#8216;<a href="http://www.ibm.com/developerworks/xml/library/x-desktop/index.html#h2">cluepackets</a>&#8216;) and matched content is provided to the gadget at runtime.</p>
<p>Extractors, optional filters, and scope declarations (used by the installer of a gadget to decide whether to install or not based upon privacy and security requirements) are defined in a manifest, along with references to the gadgets themselves, via gadget spec files, that are to be triggered.</p>
<p><img class="size-medium wp-image-804 alignright" title="Add it now" src="http://www.pipetree.com/qmacro/blog/wp-content/uploads/2010/06/additnow.png" alt="additnow" width="228" height="84" /></p>
<p>What makes these Gmail contextual gadgets even more attractive is the Google Apps Marketplace, where developers can make gadgets available, and consumers can use the &#8220;<a href="https://www.google.com/support/a/bin/answer.py?hl=en&amp;answer=172482">Add it now</a>&#8221; button to start using them in their own domains.</p>
<p>Developing Gmail contextual gadgets is relatively straightforward, but there are a few things that might cause you to stumble, such as documentation (we&#8217;re early adopters!), cacheing issues and not being completely aware of what match information is provided.</p>
<p>Despite the advent of Wave and Buzz, it&#8217;s obvious that Google sees, rightly in my opinion, a tremendous amount of value in the venerable email application, and I thought I&#8217;d take the opportunity to document my first attempt at enhancing the contextual experience with a Twitter-flavoured Gmail contextual &#8220;Hello World&#8221; gadget.</p>
<p><strong>Twitter User Info</strong></p>
<p>&#8216;Twitter User Info&#8217; is a Gmail contextual gadget that provides basic info about Twitter users whose Twitter handles appear in the email Subject line. In this example, the profile image and basic Twitter user info is shown for Joseph, whose Twitter handle <a href="http://twitter.com/@jcla1">@jcla1</a> appears in the Subject of the email from Michelle:</p>
<p><img class="alignnone size-full wp-image-812" title="Twitter User Info for @jcla1" src="http://www.pipetree.com/qmacro/blog/wp-content/uploads/2010/06/twitteruserinfoannotated.png" alt="Twitter User Info for @jcla1" width="605" height="429" /></p>
<p>The contextual gadget appears directly below the email body, and starts with the title and description &#8220;Twitter - User Info&#8221; (defined in the gadget spec) and contains HTML showing the Twitter info.</p>
<p><strong>Components and hosting</strong></p>
<p>What are the components that make up this gadget? First of all, we need the manifest and the gadget spec itself. To support the dynamic creation of contextual content in the email, we will be using <a href="http://jquery.com/">jQuery</a>, not only because it&#8217;s a fantastically useful and powerful library for manipulating web page content, but also because of Google&#8217;s intention to use <a href="http://code.google.com/p/google-caja/">Caja </a>to provide a layer of protection for the user of Javascript-based apps. The jQuery library is listed as one of the development frameworks that will be compatible with Caja. There&#8217;s also a tiny bit of CSS.</p>
<p>Beyond that, we will of course be making a call to one of the <a href="http://dev.twitter.com/">Twitter API</a> endpoints, and calling upon one of my favourite HTTP tools <a href="http://postbin.org">PostBin</a>, to dump Google gadget libary method return values for inspection.</p>
<p>While the manifest is uploaded to Google when you make your gadget available in the Marketplace, your gadget spec needs to be accessible online (so the gadget container can pull it in at the appropriate moment). There are many options for hosting content online, but for this experiment I decided to create a new App Engine application &#8216;<a href="http://qmacro-contextual.appspot.com">qmacro-contextual</a>&#8216; and host the gadget and CSS as static files there (I&#8217;m also storing the manifest there too). This might appear as overkill, but as I progress further into contextual gadget development, I will most definitely want to do some of the heavy app lifting outside of the actual gadget spec, and for this, App Engine is ideal.</p>
<p>Here&#8217;s part of the app.yaml file showing the handler declarations for the static manifest, gadget and CSS resources:</p>
<pre>application: qmacro-contextual
version: 1
runtime: python
api_version: 1

handlers:
- url: /manifests
  static_dir: manifests
  expiration: 1m

- url: /gadgets
  static_dir: gadgets
  expiration: 1m

- url: /css
  static_dir: css

- url: .*
  script: main.py<span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px;"> </span></pre>
<p>Note that I&#8217;ve specified an expiration period of 1 minute for the manifest and gadget spec directories. This is for development only, so that I can be sure that at least App Engine will serve up the resources with a very short shelf life, so that I can tweak the definitions and code and have them reloaded by the gadget container.</p>
<p>Incidentally, there&#8217;s also a URL query string parameter you can specify that causes gadget cacheing to be turned off - just append &#8220;?nogadgetcache=1&#8243; to the Gmail URL and this should do the trick.</p>
<p><strong>The Manifest</strong></p>
<p>I followed the Developer&#8217;s Guide to construct the manifest, which you can see here in full:</p>
<p><a href="http://qmacro-contextual.appspot.com/manifests/twitter-user-info.manifest.xml">http://qmacro-contextual.appspot.com/manifests/twitter-user-info.manifest.xml</a></p>
<p>The interesting parts of the manifest which relate to Gmail contextual gadgets are the Extractor, Gadget and Scope declarations.</p>
<p>The Extractor declaration looks like this:</p>
<pre>&lt;!-- EXTRACTOR --&gt;
&lt;Extension id="SubjectExtractor" type="contextExtractor"&gt;
  &lt;Name&gt;Twitter IDs in Subject&lt;/Name&gt;
  &lt;Url&gt;google.com:SubjectExtractor&lt;/Url&gt;
  &lt;Param name="subject" value=".*@[a-z]+.*"/&gt;
  &lt;Triggers ref="TwitterUserInfoGadget"/&gt;
  &lt;Scope ref="emailSubject"/&gt;
  &lt;Container name="mail"/&gt;
&lt;/Extension&gt;</pre>
<p>Each extractor (there can be more than one for any given manifest) is defined with an id and name and references a particular Extractor ID which does the work of pulling the info out of the email. Here we&#8217;re referencing <a href="http://code.google.com/apis/gmail/gadgets/contextual/#extractor">google.com:SubjectExtractor</a>, which is an extractor provided by Google for pulling out the Subject line. Google will be opening up opportunities for developers to build their own extractors if the pre-defined ones don&#8217;t provide what we need.</p>
<p>The google.com:SubjectExtractor is defined as returning one output field, @subject, which is made available to the gadget to do with as it wishes - more on that later. It also has one scope defined, tag:google.com,2010:auth/contextual/extractor/SUBJECT, which must be linked with a scope definition in a later section of the manifest.</p>
<p>We can see the reference to the @subject output field in the &lt;Param/&gt; tag. This is a filter definition, which says here that we only want the extractor to trigger the gadget if the email subject matches the given regular expression - i.e. if it contains a Twitter handle. Clearly, we want to avoid triggering gadgets when there&#8217;s nothing for the gadget to do; not only to avoid unnecessary almost-empty gadget displays, but also for performance reasons; without a filter, this extractor would fire for every email you looked at. The filter is optional, but Google recommends that even if you want to match on every occurrence, you put an explicit catch-all regular expression &#8220;.*&#8221; to make that clear.</p>
<p>The reference to &#8220;TwitterUserInfoGadget&#8221; points to the next declaration, that of the gadget itself:</p>
<pre>&lt;!-- GADGET --&gt;
&lt;Extension id="TwitterUserInfoGadget" type="gadget"&gt;
  &lt;Name&gt;Twitter User Info contextual gadget&lt;/Name&gt;
  &lt;Url&gt;http://qmacro-contextual.appspot.com/gadgets/twitter-user-info.gadget.xml&lt;/Url&gt;
  &lt;Container name="mail"/&gt;
&lt;/Extension&gt;</pre>
<p>The id of the gadget, &#8220;TwitterUserInfoGadget&#8221; is what is referred to in the &lt;Triggers/&gt; tag of the previous Extractor declaration. The gadget is a resource, located at</p>
<p><a href="http://qmacro-contextual.appspot.com/gadgets/twitter-user-info.gadget.xml">http://qmacro-contextual.appspot.com/gadgets/twitter-user-info.gadget.xml</a></p>
<p>and this is what will be requested by the Gmail contextual gadget container to pull in the gadget spec. Here&#8217;s part of an App Engine log record showing the gadget spec being fetched:</p>
<p><img class="alignnone size-full wp-image-827" title="Google Feedfetcher pulls gadget spec" src="http://www.pipetree.com/qmacro/blog/wp-content/uploads/2010/06/feedfetcherpullsgadget1.png" alt="Google Feedfetcher pulls gadget spec" width="644" height="115" /></p>
<p>The name declared in this Gadget declaration (&#8221;Twitter User Info contextual gadget&#8221;), along with the name in the Extractor declaration (&#8221;Twitter IDs in Subject&#8221;) and the general name and description from elsewhere in the manifest, are text items that appear to the Google Apps domain administrator when selecting the gadget for installation, like this:<img class="alignnone size-full wp-image-831" title="App Overview" src="http://www.pipetree.com/qmacro/blog/wp-content/uploads/2010/06/appoverview.png" alt="App Overview" width="293" height="239" /></p>
<p>Finally, we have the Scope declaration, which was indicated in the Extractor declaration earlier. This is &#8220;emailSubject&#8221;, and contains the scope URI defined for the extractor being used. There may be more than one scope for a given extractor; if this is the case, they must be each defined separately and explicitly.</p>
<pre>&lt;!-- SCOPE --&gt;
&lt;Scope id="emailSubject"&gt;
  &lt;Url&gt;tag:google.com,2010:auth/contextual/extractor/SUBJECT&lt;/Url&gt;
  &lt;Reason&gt;This application looks at the subject of each email
     looking for Twitter handles&lt;/Reason&gt;
&lt;/Scope&gt;</pre>
<p>This information appears during gadget installation, where the administrator can review what the gadget will access, and decide whether or not to proceed:</p>
<p><img class="alignnone size-full wp-image-832" title="Grant Data Access" src="http://www.pipetree.com/qmacro/blog/wp-content/uploads/2010/06/grantdataaccess.png" alt="Grant Data Access" width="635" height="312" /></p>
<p>Once you&#8217;ve defined your manifest, you must upload it as part of the overall Listing Information required to offer a gadget or an app on Google Apps Marketplace. You have to sign up to become a vendor with Google in order to do this. It&#8217;s free, as is the listing of unpublished test gadgets and apps, so you can experiment all you need to.</p>
<p><img class="alignnone size-full wp-image-836" title="Manifest" src="http://www.pipetree.com/qmacro/blog/wp-content/uploads/2010/06/manifest.png" alt="Manifest" width="444" height="289" /></p>
<p><strong>The Gadget Spec - Declarations</strong></p>
<p>Now we&#8217;ve dealt with the manifest, it&#8217;s time to turn our attention to the gadget spec. Remember that the gadget is triggered when we get a Subject line that contains one or more Twitter handles. If you&#8217;ve developed a gadget before, for iGoogle, for example, this should be familiar to you. First we have the ModulePrefs section where we declare basic gadget information and the features that we require. There&#8217;s a feature specific to Gmail contextual gadgets that we must declare here. Then we have the gadget code itself, in a CDATA section.</p>
<p>Here&#8217;s what the ModulePrefs section looks like:</p>
<pre>  &lt;ModulePrefs title="Twitter"
    description="User Info"
    height="50"
    author="DJ Adams"
    author_email="dj.adams@pobox.com"
    author_location="Manchester"&gt;

    &lt;Require feature="dynamic-height"/&gt;
    &lt;Require feature="google.contentmatch"&gt;
      &lt;Param name="extractors"&gt;
        google.com:SubjectExtractor
      &lt;/Param&gt;
    &lt;/Require&gt;
  &lt;/ModulePrefs&gt;</pre>
<p>The title and description in the module prefs shows up (”Twitter - User Info”) when the gadget is displayed at the bottom of the email. We define a height for the gadget which can be auto-adjusted later with the dynamic-height feature declared in this section too. A feature that’s specific to Gmail contextual gadgets, and that must be declared for all such gadgets, is google.contentmatch. In declaring this feature, you must list the Extractor id (or ids) that will be triggering this gadget.</p>
<p>The google.contentmatch feature gives us the facility we need to avail ourselves of the, ahem, content that was matched in this context. As you will see, we use the getContentMatches() method to do this.</p>
<p><strong>The Gadget Spec - Code</strong></p>
<p>With the ModulePrefs declarations out of the way, we get to the Javascript that breathes life into our gadget. The Javascript is defined in the &lt;Content/&gt; tag. The view type “card” is the only one supported by Gmail contextual gadgets right now.</p>
<pre>&lt;script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;

  // Expect subject as first element keyed by 'subject'
  matches = google.contentmatch.getContentMatches();
  jQuery.post('http://qmacro-postbin.appspot.com/1jd620g', 'matches:' + JSON.stringify(matches));
  var subject = matches[0]['subject'];

  // Only do something if we actually have a subject to work with
  if (subject) {

    // Pick out the twitter @handles and process them
    var handles = subject.match(/@[a-z0-9_]+/g);

    if (handles) {
      $('head').append('&lt;link rel="stylesheet" href="http://qmacro-contextual.appspot.com/css/twitter-user-info.css" /&gt;');
      for (var i = 0; i &lt; handles.length; i++) {
        var user_resource = 'http://api.twitter.com/users/show/'
                          + handles[i] + '.json?callback=?';
          $.getJSON(user_resource, function(data) {
          jQuery.post('http://qmacro-postbin.appspot.com/1jd620g', 'userinfo:' + JSON.stringify(data));
          var loc = "";
          if (data.location) {
            loc = ' (' + data.location + ')';
          }
          var tw_info = '&lt;table border="0"&gt;'
                      + '&lt;tr&gt;' + '&lt;td&gt;' + '&lt;a href="' + data.url + '"&gt;'
                      + '&lt;img src="' + data.profile_image_url + '" /&gt;' + '&lt;/a&gt;'
                      + '&lt;/td&gt;' + '&lt;td class="userinfo"&gt;'
                      + '&lt;a href="http://twitter.com/' + data.screen_name + '"&gt;@'
                      + data.screen_name + '&lt;/a&gt;' + '&lt;br /&gt;' + data.name + loc + '&lt;br /&gt;'
                      + data.description + '&lt;/td&gt;' + '&lt;/tr&gt;&lt;/table&gt;';
          jQuery(tw_info).appendTo('body');
        });
      }
      gadgets.window.adjustHeight(100);
    }
  }

&lt;/script&gt;<span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: small;"><span>
</span></span></pre>
<p>First, we pull in the jQuery library with a &lt;script/&gt; tag, and then we’re off with our gadget code.</p>
<p>We use the google.contentmatch.getContentMatches() method to pull in the matches supplied to us by the Extractor. One of my favourite phrases is “<a href="http://en.wikiquote.org/wiki/Only_Fools_and_Horses#Chain_Gang_.5B6.3.5D">let the dog see the rabbit</a>” - let’s have a look at the data, in this case. What does the getContentMatches() actually return? What does it look like? This is where the rather useful PostBin comes in to play. When we get the response from the call to getContentMatches(), encode it into a JSON string form with JSON.stringify() and bung the whole lot to a Postbin too see. Easy! Of course, this is only appropriate for development and debugging - I’d remove it for a production gadget. By the way, I&#8217;m running my own instance of Postbin - you can <a href="http://github.com/progrium/postbin">run you own instance</a> too.</p>
<p><img class="alignleft size-full wp-image-886" title="Matches in Postbin" src="http://www.pipetree.com/qmacro/blog/wp-content/uploads/2010/06/matchesinpostbin1.png" alt="Matches in Postbin" width="345" height="84" />So from looking at what we get, we can see that what we’re after is the value of the ’subject’ key in the first element of the matches array.</p>
<p>By definition, we’re only instantiated because there was a Twitter handle in the Subject. There could be more than one, of course. After collecting them into a handles array, we’re ready to process each one. First, though - we pull in the CSS resource to the current document. The resource is served as a static file from the App Engine app:</p>
<p><a href="http://qmacro-contextual.appspot.com/css/twitter-user-info.css">http://qmacro-contextual.appspot.com/css/twitter-user-info.css</a></p>
<p>For each of the Twitter handles, we want to display some basic info, as shown in the screenshot earlier. To retrieve this, we make a simple call to the Twitter API. Specifically,</p>
<p><a href="http://apiwiki.twitter.com/Twitter-REST-API-Method:-users%C2%A0show">http://api.twitter.com/users/show/[Twitter-handle].json?callback=</a>?</p>
<p>will give us a nice chunk of JSON with the information we want, like this:</p>
<pre>{
 "description":"Developer and Linux Expert",
 "screen_name":"Jcla1",
 "url":"http://www.pipetree.com/josephadams",
 "name":"Joseph Adams",
 "profile_image_url":"http://a1.twimg.com/profile_images/106288960/JosephWithLomaxCar_normal.jpg",
 "location":"Krefeld,Germany",
 ...
}</pre>
<p>I’d originally started with the<a href="http://plugins.jquery.com/project/jtwitter"> jTwitter</a> jQuery plugin but found that it didn’t quite do what I wanted, and in any case using the Twitter API from jQuery is straightforward anyway. But thank you <a href="http://plugins.jquery.com/user/9986">uzbekjon</a> for getting me started.</p>
<p>You can see from the code that I’m making more use of Postbin, by gratuitously dumping the results of the Twitter API call in there too. I like to see what I’m dealing with. <a href="http://search.cpan.org/perldoc?Data::Dumper">Data::Dumper</a> is my alltime favourite Perl module, if you hadn&#8217;t guessed.</p>
<p>Once we have the info from Twitter, it’s just a simple matter of constructing some HTML, making use of the CSS via the ‘userinfo’ class, and appending that to the email. Job done!</p>
<p>I&#8217;ve pushed my fledgeling <a href="http://github.com/qmacro/qmacro-contextual">qmacro-contextual App Engine project to Github</a>, so you can take a look and create your own &#8220;Hello World&#8221; Gmail contextual gadget.</p>
<p>Share and enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pipetree.com/qmacro/blog/2010/06/getting-started-with-gmail-contextual-gadgets/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Scratching an itch - Magic The Gathering card info</title>
		<link>http://www.pipetree.com/qmacro/blog/2010/03/scratching-an-itch-magic-the-gathering-card-info/</link>
		<comments>http://www.pipetree.com/qmacro/blog/2010/03/scratching-an-itch-magic-the-gathering-card-info/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 21:12:35 +0000</pubDate>
		<dc:creator>dj</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[appengine]]></category>

		<category><![CDATA[bookmarklet]]></category>

		<category><![CDATA[http]]></category>

		<category><![CDATA[joseph]]></category>

		<category><![CDATA[mtg]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[reading]]></category>

		<guid isPermaLink="false">http://www.pipetree.com/qmacro/blog/?p=783</guid>
		<description><![CDATA[Well over 10 years ago I bought a box set of Magic The Gathering (MTG) cards. I wasn&#8217;t really sure what they were, but they looked fascinating. Unfortunately, they gathered dust after a while, mostly because there wasn&#8217;t anyone else to play against, and I didn&#8217;t understand the rules properly anyway. Fast forward to 2009. [...]]]></description>
			<content:encoded><![CDATA[<p>Well over 10 years ago I bought a box set of <a href="http://www.magicthegathering.com" target="_self">Magic The Gathering</a> (MTG) cards. <a href="http://www.magicthegathering.com"><img class="size-medium wp-image-784 alignleft" style="border: 10px solid white;" title="Magic The Gathering" src="http://www.pipetree.com/qmacro/blog/wp-content/uploads/2010/03/mtg-215x300.jpg" alt="Magic The Gathering" width="215" height="300" /></a>I wasn&#8217;t really sure what they were, but they looked fascinating. Unfortunately, they gathered dust after a while, mostly because there wasn&#8217;t anyone else to play against, and I didn&#8217;t understand the rules properly anyway. Fast forward to 2009. My son <a href="http://www.pipetree.com/josephadams/" target="_self">Joseph</a>, having discovered and dusted off the box set, taught me how to play, at at Starbucks cafe over a few hot chocolates and cappuccinos on a cold winter afternoon.</p>
<p>Hooked!</p>
<p>Since then we&#8217;ve been fans of the game of endless possibilities and ever changing scope and interest, and almost regulars at our local MTG store, <a href="http://www.fanboy3.co.uk" target="_self">Fan Boy Three</a> on Newton St in Manchester.</p>
<p>So to educate myself in all thing Magic, I turned to MTG&#8217;s official website, Wizards of the Coast&#8217;s <a href="http://www.wizards.com/Magic/Multiverse/" target="_self">The Multiverse</a>, and in particular, to their incredibly prolific set of column authors on the <a href="http://www.wizards.com/Magic/Magazine/Default.aspx" target="_self">Daily MTG</a>. More <a href="http://www.wizards.com/Magic/Magazine/Archive.aspx?tag=news,feature,column,event" target="_self">articles </a>on design, deck construction, strategy and match reports than you could shake a <a href="http://www.wizards.com/Magic/TCG/Article.aspx?x=magic/planeswalkers/week4" target="_self">Planeswalker</a> card at.</p>
<p>But while I <a href="http://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/16597" target="_self">read a lot</a>, the majority of it is on paper, in the bath, on the train, an<a href="http://gatherer.wizards.com/Pages/Card/Details.aspx?name=Skirk%20Ridge%20Exhumer"><img class="size-medium wp-image-790 alignright" style="border: 5px solid white;" title="Skirk Ridge Exhumer" src="http://www.pipetree.com/qmacro/blog/wp-content/uploads/2010/03/skirkridgeexhumer-215x300.jpg" alt="Skirk Ridge Exhumer" width="215" height="300" /></a>d soaking up the countless minutes lost at the start of every meeting, while you wait for people to get started, fail to get the projector working, fetch coffees or fiddle with the air conditioning. And on paper, the MTG articles are good, but for a novice like me, there&#8217;s something missing. The articles make lots of references to cards by name, and when reading online, there&#8217;s a nice popup of the card details so you can see what the author is talking about. But on paper?</p>
<p>So I had an itch to scratch. What I wanted was an accompanying printout of the cards mentioned in any given Daily MTG article. So when the author referred to <a onmouseover="OpenTip(event, &quot;Hedron Crab&quot;)" href="http://gatherer.wizards.com/Pages/Card/Details.aspx?name=Hedron%20Crab" target="_blank">Hedron Crab</a>, <a class="nodec" onmouseover="OpenTip(event, &quot;Pitfall Trap&quot;)" href="javascript:autoCardWindow('Pitfall_Trap')"></a> <a onmouseover="OpenTip(event, &quot;Baloth Woodcrasher&quot;)" href="http://gatherer.wizards.com/Pages/Card/Details.aspx?name=Baloth%20Woodcrasher" target="_blank">Baloth Woodcrasher</a> or <a onmouseover="OpenTip(event, &quot;Oran-Rief, the Vastwood&quot;)" href="http://gatherer.wizards.com/Pages/Card/Details.aspx?name=Oran-Rief,%20the%20Vastwood" target="_blank">Oran-Rief, the Vastwood</a> I would know what they were talking about.</p>
<p>I decided to use <a href="http://code.google.com/appengine" target="_self">Google App Engine</a>, and have my Python HTTP responder in the cloud. I created a very simple app &#8220;mtgcardinfo&#8221;, part of my Github-hosted scratchpad area <a href="http://github.com/qmacro/gae-qmacro" target="_self">gae-qmacro</a>. Given the URL of an MTG article, the app uses urlfetch() to go and get it, parses out the card names, and produces an HTML response with a whole load of image references. Luckily the card detail popups in the articles are powered by Javascript and are great indicators of card names for anyone who cares to wield a regex to look for them.</p>
<p>And of course to glue it all together, I used a <a href="http://en.wikipedia.org/wiki/Bookmarklet" target="_self">bookmarklet</a>, so I could jump to the list of cards while directly in the article.</p>
<p>So if you&#8217;re interested, have a go: <a href="http://qmacro.appspot.com/mtgcardinfo" target="_blank">http://qmacro.appspot.com/mtgcardinfo</a>.</p>
<p>The combination of App Engine, Python, HTTP and Javascript is rapidly becoming my new Swiss Army Knife of choice in the web-based online world. And the best thing? I&#8217;m teaching Joseph this stuff, and not only is he incredibly good at it, he *loves* it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pipetree.com/qmacro/blog/2010/03/scratching-an-itch-magic-the-gathering-card-info/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Mainframes and the cloud - everything old is new again</title>
		<link>http://www.pipetree.com/qmacro/blog/2009/09/mainframes-and-the-cloud-everything-old-is-new-again/</link>
		<comments>http://www.pipetree.com/qmacro/blog/2009/09/mainframes-and-the-cloud-everything-old-is-new-again/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 17:00:59 +0000</pubDate>
		<dc:creator>dj</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[appengine]]></category>

		<category><![CDATA[azure]]></category>

		<category><![CDATA[cloudcomputing]]></category>

		<category><![CDATA[ec2]]></category>

		<category><![CDATA[ibm]]></category>

		<category><![CDATA[ims]]></category>

		<category><![CDATA[mainframe]]></category>

		<category><![CDATA[mvs]]></category>

		<category><![CDATA[sap]]></category>

		<guid isPermaLink="false">http://www.pipetree.com/qmacro/blog/?p=780</guid>
		<description><![CDATA[Cloud computing, virtual machines. It&#8217;s big business. Amazon has its Elastic Compute Cloud (EC2) which provides &#8220;resizable compute capacity in the cloud&#8220;, Microsoft has Azure, providing &#8220;on-demand compute and storage to host, scale, and manage Web applications on the Internet&#8221; and Google&#8217;s offering is App Engine which offers &#8220;the ability to build and host web [...]]]></description>
			<content:encoded><![CDATA[<p>Cloud computing, virtual machines. It&#8217;s big business. Amazon has its <a href="http://aws.amazon.com/ec2/">Elastic Compute Cloud</a> (EC2) which provides &#8220;<em>resizable compute capacity in the cloud</em>&#8220;, Microsoft has <a href="http://www.microsoft.com/azure/default.mspx">Azure</a>, providing &#8220;<em>on-demand compute and storage to host, scale, and manage Web applications on the Internet</em>&#8221; and Google&#8217;s offering is <a href="http://code.google.com/appengine/">App Engine</a> which offers &#8220;<em>the ability to build and host web applications on <em>Google&#8217;s</em> infrastructure</em>&#8220;. As you might know, I&#8217;m personally very <a href="http://www.pipetree.com/qmacro/blog/tag/appengine/">taken with</a> App Engine.</p>
<p>The offerings are slightly different - for example, while EC2 is bare virtual hardware, App Engine is a web application platform in the cloud. But they all have similar pricing arrangements, based generally on uptime or CPU time, I/O  and storage.</p>
<p>Does this seem familiar to you? It does to me, but then again, I did just turn 0&#215;2B this month. In 1988 I was working in the Database Support Group at a major energy company in London, looking after the SAP R/2 databases, which were powered by IMS DB/DC, on MVS - yes, IBM big iron mainframes. I still look back on those days with <a href="http://radar.oreilly.com/2005/11/burn-in-7-dj-adams.html">fond memories</a>.</p>
<p>In reviewing some 3rd party software, I wrote a document entitled &#8220;<strong>BMC Software&#8217;s Image Copy Plus: An Evaluation</strong>&#8220;. BMC&#8217;s Image Copy Plus was a product which offered faster image copies of our IMS DB (VSAM) databases. (Image Copy Plus, as well as IMS, is <a href="http://www.bmc.com/products/product-listing/23026-2064-1201.html">still around</a>, over 20 years on! But that has to be the subject of another post).</p>
<p>One of the sections of the evaluation was to compare costs, as well as time &#8212; by how much would the backup costs be reduced using BMC&#8217;s offering?</p>
<p>And have a guess on what the cost comparison was based? Yes. CPU time, I/O (disk and tape <a href="http://www.reference.com/browse/wiki/EXCP">EXCP</a>s) and actual tapes.</p>
<p><a title="Mainframe Job Billing by qmacro, on Flickr" href="http://www.flickr.com/photos/qmacro/3904246258/"><img src="http://farm4.static.flickr.com/3454/3904246258_5c5cdf2108.jpg" alt="Mainframe Job Billing" width="500" height="348" /></a></p>
<p>Everything old is new again.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pipetree.com/qmacro/blog/2009/09/mainframes-and-the-cloud-everything-old-is-new-again/feed/</wfw:commentRss>
		</item>
		<item>
		<title>SAP and Google Wave - Conversation Augmentation</title>
		<link>http://www.pipetree.com/qmacro/blog/2009/09/sap-and-google-wave-conversation-augmentation/</link>
		<comments>http://www.pipetree.com/qmacro/blog/2009/09/sap-and-google-wave-conversation-augmentation/#comments</comments>
		<pubDate>Tue, 08 Sep 2009 06:58:25 +0000</pubDate>
		<dc:creator>dj</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[appengine]]></category>

		<category><![CDATA[dashboard]]></category>

		<category><![CDATA[http]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[rest]]></category>

		<category><![CDATA[sap]]></category>

		<category><![CDATA[wave]]></category>

		<guid isPermaLink="false">http://www.pipetree.com/qmacro/blog/?p=770</guid>
		<description><![CDATA[It&#8217;s been pretty much six years to the day since I last wrote here about Dashboard, Nat Friedman&#8217;s project and implementation of a realtime contextual information system. So I thought it fitting to make a short demo showing integration between Google Wave and SAP, inspired by the cluepacket-driven style shown so nicely with Dashboard.
I got [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been pretty much six years to the day since <a href="http://www.pipetree.com/qmacro/blog/tag/dashboard/" target="_self">I last wrote here about Dashboard</a>, Nat Friedman&#8217;s project and implementation of a realtime contextual information system. So I thought it fitting to make a short demo showing integration between Google Wave and SAP, inspired by the cluepacket-driven style shown so nicely with Dashboard.</p>
<p>I got my Wave Sandbox account a week or so ago, and have had a bit of time to have a look at how robots and gadgets work &#8212; the two main Wave extension mechanisms. To get my feet wet, I built a robot, which is hosted in the cloud using Google App Engine, another <a href="http://www.pipetree.com/qmacro/blog/tag/appengine/" target="_self">area of interest to me</a>, and the subject of this weblog entry. I used Python, but there&#8217;s also a Java client library available too. You can get more info in the <a href="http://code.google.com/apis/wave/guide.html" target="_self">API Overview</a>.</p>
<p>What this robot does is listen to conversations in a Wave, automatically recognising SAP entities and augmenting the conversation by inserting extra contextual information directly into the flow. In this example, the robot can recognise transport requests, and will insert the request&#8217;s description into the conversation, lending a bit more information to what&#8217;s being discussed.</p>
<p>The robot recognises transport requests by looking for a pattern:</p>
<pre>trkorr_match = re.search(' (SAPK\w{6}|[A-Z0-9]{3}K\d{6}) ', text)</pre>
<p>In other words, it&#8217;s looking for something starting SAPK followed by six further characters, or something starting with 3 characters, followed by a K and six digits (the more traditional customer-orientated request format). In either case, there must be a space before and a space following, to be more sure of it being a &#8216;word&#8217;.</p>
<p>How does it retrieve the description for a recognised transport request? Via a simple REST-orientated interface, of course <img src='http://www.pipetree.com/qmacro/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> I use the excellent Internet Communication Framework (ICF) to build and host HTTP handlers so I can <a href="https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/584" target="_top">expose SAP functionality and data as resources in a uniform and controlled way</a>. Each piece of data worth talking about is a <a href="http://www.pipetree.com/qmacro/blog/2009/06/information-vs-behaviour/">first class citizen on the web</a>; that is, each piece of data is a resource, and has a URL.</p>
<p>So the robot simply fetches the default representation of the recognised request&#8217;s &#8216;description&#8217; resource. If the request was NSPK900115, the description resource&#8217;s URL would be something like:</p>
<pre>http://hostname:port/transport/request/NSPK900115/description</pre>
<p>Once fetched, the description is inserted into the conversation flow.</p>
<p><object width="560" height="340" data="http://www.youtube.com/v/G7W2M6H3OQo&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/G7W2M6H3OQo&amp;hl=en&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /></object></p>
<p><a href="http://www.youtube.com/watch?v=G7W2M6H3OQo">http://www.youtube.com/watch?v=G7W2M6H3OQo</a></p>
<p>(<a href="http://weblogs.sdn.sap.com/pub/wlg/15721">Originally written on SDN</a> but republished here because of portal access issues)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pipetree.com/qmacro/blog/2009/09/sap-and-google-wave-conversation-augmentation/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Book review: &#8220;SAP Business ONE Implementation&#8221;</title>
		<link>http://www.pipetree.com/qmacro/blog/2009/08/book-review-sap-business-one-implementation/</link>
		<comments>http://www.pipetree.com/qmacro/blog/2009/08/book-review-sap-business-one-implementation/#comments</comments>
		<pubDate>Mon, 31 Aug 2009 10:28:04 +0000</pubDate>
		<dc:creator>dj</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[businessone]]></category>

		<category><![CDATA[review]]></category>

		<category><![CDATA[sap]]></category>

		<guid isPermaLink="false">http://www.pipetree.com/qmacro/blog/?p=766</guid>
		<description><![CDATA[A short while ago I was sent a review copy of “SAP Business ONE Implementation”, by Wolfgang Niefert, published by Packt Publishing. On receipt, I skimmed through it, and my first impressions were very favourable. I&#8217;m now reading through it a second time as I sit with a cup of tea and a slice of [...]]]></description>
			<content:encoded><![CDATA[<p style="margin-bottom: 0in;">A short while ago I was sent a review copy of “<a href="http://www.packtpub.com/sap-business-1-implementation/book">SAP Business ONE Implementation</a>”, by Wolfgang Niefert, published by Packt Publishing. On receipt, I skimmed through it, and my first impressions were very favourable. I&#8217;m now reading through it a second time as I sit with a cup of tea and a slice of cake in North Wales on a Bank Holiday weekend, and I&#8217;m happy to say that my opinion hasn&#8217;t changed.</p>
<p style="margin-bottom: 0in;">To give you a bit of background, I&#8217;m <a href="http://www.pipetree.com/qmacro/">an SAP veteran</a> of 22 years – starting out with R/2 version 4.1d in 1987, moving through R/3 in the mid-90&#8217;s and on to Enterprise and beyond. But this is the first time I&#8217;ve studied SAP Business ONE in any detail. So while I have a lot of experience of SAP&#8217;s traditional products, I&#8217;m approaching SAP Business ONE, and “SAP Business ONE Implementation” more as the potential owner of a small business.</p>
<p style="margin-bottom: 0in;">I certainly haven&#8217;t been disappointed. “SAP Business ONE Implementation” is written “for technically savvy business owners, entrepreneurs and departmental managers”. And I think by and large the book does a great job of reaching out to and connecting with exactly that audience. I <span style="text-decoration: none;"><span><em>was</em> expecting the book to be a fairly technically orientated implementation how-to. But it is more than that. It takes you from business first principles, connecting well at the level of sales, delivery, inventory, warehousing, manufacturing and other business challenges. It explains how SAP Business ONE is designed to address those challenges, and guides you through installation, implementation and some configuration of the system. Once the basics have been established, it moves further to cover project planning, reporting and analysis, business process analysis, customer relationship management, logistics &amp; supply chain management, contract management, and ends up addressing, albeit briefly, more complex reporting tools and topics, data migration, and electronic commerce.</span></span></p>
<p style="margin-bottom: 0in; text-decoration: none;">The book has fewer than 300 pages. A book that addresses the areas that this book does could easily be twice that size. But that&#8217;s where this book does well. It&#8217;s an approachable, undaunting and really rather good introduction to running your business with SAP Business ONE. The writing style is very easygoing, and informative without being patronising. There are plenty of examples, and all the screenshots you&#8217;d need. It doesn&#8217;t try to be a reference book. It does try to be a sort of hybrid guide to solving the business <em>and</em> technical challenges of running a small or medium sized company using SAP software, and I would say that it succeeds.</p>
<p style="margin-bottom: 0in; text-decoration: none;">If you&#8217;re a small business owner considering stepping up and taking control of your business with SAP Business ONE, if you&#8217;ve already got SAP Business ONE and want to explore more application features at a high level, or if even if (like me) you&#8217;re an SAP hacker wanting to learn about what SAP Business ONE can do, then you could do a lot worse than grab a copy of this book.</p>
<p style="margin-bottom: 0in; text-decoration: none;">
<p style="margin-bottom: 0in; text-decoration: none;">
]]></content:encoded>
			<wfw:commentRss>http://www.pipetree.com/qmacro/blog/2009/08/book-review-sap-business-one-implementation/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Dealing with &#8220;#blogtheft&#8221; from SAP&#8217;s Developer Network</title>
		<link>http://www.pipetree.com/qmacro/blog/2009/08/dealing-with-blogtheft-from-saps-developer-network/</link>
		<comments>http://www.pipetree.com/qmacro/blog/2009/08/dealing-with-blogtheft-from-saps-developer-network/#comments</comments>
		<pubDate>Fri, 28 Aug 2009 15:14:53 +0000</pubDate>
		<dc:creator>dj</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[apache]]></category>

		<category><![CDATA[blogtheft]]></category>

		<category><![CDATA[modrewrite]]></category>

		<category><![CDATA[sap]]></category>

		<category><![CDATA[sdn]]></category>

		<guid isPermaLink="false">http://www.pipetree.com/qmacro/blog/?p=745</guid>
		<description><![CDATA[Recently it has come to people&#8217;s attention that there is a website www.sap-abap4.com out there with a lot of very interesting content &#8230; which seems to have been completely &#8220;lifted&#8221; from the SAP Developer Network (SDN) and reproduced verbatim, except that in each case the original author name has been removed!
Lots of discussion is taking [...]]]></description>
			<content:encoded><![CDATA[<p>Recently it has <a href="http://search.twitter.com/search?q=%23blogtheft">come to people&#8217;s attention</a> that there is a website www.sap-abap4.com out there with a lot of very interesting content &#8230; which seems to have been <em>completely</em> &#8220;lifted&#8221; from the <a href="http://www.sdn.sap.com">SAP Developer Network</a> (SDN) and reproduced verbatim, except that in each case the original author name has been removed!</p>
<p>Lots of discussion is taking place how best to deal with this. One way (and I&#8217;m posting it as a blog entry as much for my memory&#8217;s sake as anything else) is to conditionally rewrite requests for images. I&#8217;m using Apache and therefore the <a href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html">mod_rewrite</a> extension is my tool of choice.</p>
<p>It just so happens that there are a couple of screenshots in a recent SDN blog entry of mine &#8220;<a href="https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/14469">A return to the SDN community, and a touch of Javascript</a>&#8221; and these images are hosted on my own server at <a href="http://www.pipetree.com">www.pipetree.com</a>.</p>
<p>So as a little test, I can control the requests for these images, rewriting those requests so that a different image is served depending on the request&#8217;s referrer &#8212; the URL of the page that the images are referenced on with an &lt;img /&gt; tag.</p>
<p>So with some mod_rewrite voodoo in a local .htaccess file:</p>
<pre>RewriteEngine On
RewriteCond %{HTTP_REFERER} ^http://www\.sap-abap4\.com
RewriteBase /qmacro/x
RewriteRule ^SdnPageTitle(Fixed|Broken)_small\.jpg$ StolenContent.png [L]</pre>
<p>I can send a &#8216;StolenContent.png&#8217; image, if the referrer is from the rogue site.</p>
<p>The result of the rewrite is that when viewed on SDN, the blog entry looks fine, and the screenshot images look as they&#8217;re supposed to:</p>
<div id="attachment_760" class="wp-caption alignnone" style="width: 472px"><img class="size-full wp-image-760" title="screenshot-sdn3" src="http://www.pipetree.com/qmacro/blog/wp-content/uploads/2009/08/screenshot-sdn3.jpg" alt="Images appear as they're supposed to" width="462" height="500" /><p class="wp-caption-text">Images appear as they&#39;re supposed to</p></div>
<p>But when the images are used on www.sap-abap4.com, they will appears differently:</p>
<div id="attachment_761" class="wp-caption alignnone" style="width: 472px"><img class="size-full wp-image-761" title="screenshot-sap-abap41" src="http://www.pipetree.com/qmacro/blog/wp-content/uploads/2009/08/screenshot-sap-abap41.jpg" alt="Image appears differently" width="462" height="500" /><p class="wp-caption-text">Image appears differently</p></div>
<p>So there you have it. It&#8217;s not a complete solution to the problem by any means, but it at least will alert unsuspecting readers of that website to what&#8217;s happening (if you&#8217;re testing yourself, you might have to refresh the pages in your browser, as it will probably have cached the first version of each image). Perhaps the SAP community network team can apply this technique for the images hosted on SDN.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pipetree.com/qmacro/blog/2009/08/dealing-with-blogtheft-from-saps-developer-network/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Command lines of the future, and simplicity of integration</title>
		<link>http://www.pipetree.com/qmacro/blog/2009/08/command-lines-of-the-future-and-simplicity-of-integration/</link>
		<comments>http://www.pipetree.com/qmacro/blog/2009/08/command-lines-of-the-future-and-simplicity-of-integration/#comments</comments>
		<pubDate>Fri, 21 Aug 2009 11:10:12 +0000</pubDate>
		<dc:creator>dj</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[chatbot]]></category>

		<category><![CDATA[http]]></category>

		<category><![CDATA[irc]]></category>

		<category><![CDATA[jabber]]></category>

		<category><![CDATA[pubsubhubbub]]></category>

		<category><![CDATA[purl]]></category>

		<category><![CDATA[rest]]></category>

		<category><![CDATA[roa]]></category>

		<category><![CDATA[sap]]></category>

		<category><![CDATA[soa]]></category>

		<category><![CDATA[wave]]></category>

		<category><![CDATA[webhooks]]></category>

		<category><![CDATA[xmpp]]></category>

		<guid isPermaLink="false">http://www.pipetree.com/qmacro/blog/?p=727</guid>
		<description><![CDATA[This is a bit of a hand-wavy post, but I wanted to get my thoughts down. Recently there&#8217;s been a spate of interest around interaction with devices, applications and systems &#8230; via a chat-style interface. This is nothing new, of course. Bots have existed on the IRC networks for a long time. The venerable Purl, [...]]]></description>
			<content:encoded><![CDATA[<p>This is a bit of a hand-wavy post, but I wanted to get my thoughts down. Recently there&#8217;s been a spate of interest around interaction with devices, applications and systems &#8230; via a chat-style interface. This is nothing new, of course. Bots have existed on the IRC networks for a long time. The venerable <a href="http://www.foo.be/docs/tpj/issues/vol3_2/tpj0302-0002.html">Purl</a>, an <a href="http://en.wikipedia.org/wiki/Infobot">infobot</a>, was a particular favourite of mine. When instant messaging (IM) came along, we had a new chat interface - which took the form of one-on-one or conference (&#8217;group&#8217;) chat. With <a href="http://www.jabber.org/">Jabber</a> (XMPP), &#8216;Chatbot&#8217; was a favourite in the various conference rooms. Back in late 2002, I even wrote about Chatbot in a 2-part series &#8220;The Command Line of the Future&#8221; (&#8221;<a href="http://openp2p.com/pub/a/p2p/2002/01/11/jabber_bots.html">Is Jabber&#8217;s Chatbot the Command Line of the Future?</a>&#8221; and The &#8220;<a href="http://openp2p.com/pub/a/p2p/2002/02/08/chatbot_two.html">Command Line of the Future Part 2: Expanding Chatbot&#8217;s Repertoire</a>&#8220;):</p>
<blockquote><p>Consider for a moment what this command line of the future might look like. More and more people are online. More and more people are permanently  connected, whether it be through DSL, cable, or 802.11 technology. And more and more of these people are communicating. Talking. Having conversations. In addition to email and Internet Relay Chat, or IRC, the (relatively) new kid on the block, Instant messaging (IM), is playing a huge part in facilitating these conversations. And in the same way that it&#8217;s common for us to have a command prompt or three sitting on our graphical desktop, it&#8217;s also becoming common to have chat windows more or less permanently open on the desktop too.</p></blockquote>
<blockquote><p><!-- sidebar begins --> <!-- don't move sidebars --> <!-- sidebar ends -->But when thinking of IM, why stop at conversations with people? The person-to-application (P2A) world isn&#8217;t the exclusive domain of the Web. Bots, applications or utilities that have their interface as a projection of a persona into the online chat world, are a great and fun way to bring people and applications together in a conversational way.</p>
<p>Interacting with a bot is the same as interacting with a person: type something to it and it replies. And what&#8217;s more, because of the similarities between a classic command-line prompt and that of a chat window, where you&#8217;re talking with a bot &#8212; both scenarios are text-based &#8212; interaction with a bot is scriptable.</p></blockquote>
<p>Forward to the present.</p>
<p>Just the other day, <a href="http://twitter.com/davemee">@davemee</a> and <a href="http://twitter.com/technicalfault">@technicalfault</a> alerted me to <a href="http://twitter.com/manairport">@manairport</a>, Manchester Airport&#8217;s online persona on Twitter, obviously yet another chat-style interface. You can interact with it via direct messages (DMs). You follow it, it will follow you back, and you&#8217;re away.</p>
<blockquote>
<pre>me: d manairport be7217</pre>
<pre>manairport: Received request for information: be7217
manairport: Status of 17:40 flight BE7217 to Dusseldorf
            departing T3: Scheduled 17:40</pre>
</blockquote>
<p>Nice and <a href="http://www.dopplr.com/trip/qmacro/825806">useful</a>!</p>
<p>And then just this morning, I read a weblog post on <a href="http://www.sdn.sap.com">SDN</a> entitled &#8220;<a href="https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/15521">SAP Enterprise Service and Google Wave</a>&#8220;. In it, the author talks about connecting Google Wave (you guessed it, yet another chat-style interface, amongst other things) with SAP, in particular enterprise &#8217;services&#8217;. In the short demo, order information from an SAP system is retrieved in a conversational way. The concept is great. The obvious issue with what&#8217;s shown in the demo (and I know it&#8217;s only a proof of concept) is that the bot responds with a data structure dump of information. What we&#8217;re looking for is something more, well, consumable by humans. Smaller, more distinct and addressable pieces of information that can be returned and be useful.</p>
<p>But what was more telling, at least to me, were the difficulties he described in connecting to the complex Enterprise Service backend in SAP:</p>
<blockquote><p>&#8220;&#8230; find the webservice &#8230; create a proxy &#8230; I did have some problems with calling the ES &#8230; On Appengine there are some limitations on what you can call of Java classes &#8230; From an architectural point I&#8217;m not real proved of the solution&#8230;&#8221;</p></blockquote>
<p>Hmm. Why does architecture have to be complex? Using Enterprise Services, using SOA, is more complex than it needs to be. There&#8217;s a reason why the web works. There&#8217;s a reason why Google designed App Engine&#8217;s backend infrastructure (including <a href="http://googleappengine.blogspot.com/2009/06/new-task-queue-api-on-google-app-engine.html">asynchronous task queues</a>) in a simple HTTP-orientated way. There&#8217;s a reason why the Wave robot protocol is based on simple HTTP mechanisms. There&#8217;s a reason why mechanisms like <a href="http://code.google.com/p/pubsubhubbub/">PubSubHubBub</a> and <a href="http://webhooks.pbworks.com/">Webhooks</a> are based on HTTP as an application protocol. Because simple works, and it works well.</p>
<p>Let&#8217;s come back to the &#8220;smaller, more distinct and addressable&#8221; issue. If we let ourselves be guided by a Resource Orientated Architecture (ROA) approach, rather than a Service Orientated Architecture (SOA) approach, we end up with simpler application protocols, flexible, reliable and transparent integration, and pieces of information that are addressable &#8212; and <a href="https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/584">usable</a> &#8212; first class citizens on the web. This is Twitter&#8217;s <a href="http://www.pipetree.com/qmacro/blog/2009/05/twitters-success/">killer feature</a>.</p>
<p>Enterprises suffer enough with complexity paralysis. We should endeavour to embrace the design of HTTP as an application protocol (which is what I&#8217;m doing with <a href="http://wiki.github.com/qmacro/coffeeshop">Coffeeshop</a>), rather than fight against it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pipetree.com/qmacro/blog/2009/08/command-lines-of-the-future-and-simplicity-of-integration/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Coffeeshop screencast: HTTP conneg, resource representations and JSON</title>
		<link>http://www.pipetree.com/qmacro/blog/2009/08/coffeeshop-screencast-http-conneg-resource-representations-and-json/</link>
		<comments>http://www.pipetree.com/qmacro/blog/2009/08/coffeeshop-screencast-http-conneg-resource-representations-and-json/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 10:24:47 +0000</pubDate>
		<dc:creator>dj</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[appengine]]></category>

		<category><![CDATA[coffeeshop]]></category>

		<category><![CDATA[conneg]]></category>

		<category><![CDATA[http]]></category>

		<category><![CDATA[json]]></category>

		<category><![CDATA[perl]]></category>

		<category><![CDATA[pipeline]]></category>

		<category><![CDATA[pubsub]]></category>

		<category><![CDATA[rest]]></category>

		<guid isPermaLink="false">http://www.pipetree.com/qmacro/blog/?p=719</guid>
		<description><![CDATA[After yesterday&#8217;s screencast showing the use of coffeeshop from the command line, here&#8217;s one that expands upon the direction I&#8217;m taking the implementation, following the REST/HTTP philosophy. It shows, I hope, that embracing REST-orientated HTTP features, such as content negotiation (&#8221;conneg&#8221;), and the concepts of resources and representations, gives you a fantastically flexible and straightforward [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://www.pipetree.com/qmacro/blog/2009/08/2nd-coffeeshop-resthttp-screencast/">yesterday&#8217;s screencast</a> showing the use of <a href="http://wiki.github.com/qmacro/coffeeshop">coffeeshop</a> from the command line, here&#8217;s one that expands upon the direction I&#8217;m taking the implementation, following the <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a>/HTTP philosophy. It shows, I hope, that embracing REST-orientated HTTP features, such as <a href="http://en.wikipedia.org/wiki/Content_negotiation">content negotiation</a> (&#8221;conneg&#8221;), and the concepts of <a href="http://bitworking.org/news/How_to_create_a_REST_Protocol">resources and representations</a>, gives you a fantastically flexible and straightforward application protocol to work with and be guided by. (I&#8217;m <a href="http://twitter.com/qmacro/status/3306694041">not</a> doing full-blown conneg, that will come later. But what I am doing works well for me).</p>
<p><object width="560" height="340" data="http://www.youtube.com/v/NhAWH2-Quuk&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/NhAWH2-Quuk&amp;hl=en&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /></object></p>
<p><a href="http://www.youtube.com/watch?v=NhAWH2-Quuk">http://www.youtube.com/watch?v=NhAWH2-Quuk</a></p>
<p>In this shorter screencast, I continue on from where I left off &#8212; viewing the message detail resource in the web browser. I  use conneg to request that same resource in <a href="http://www.json.org/">JSON</a> instead of HTML, and show how the JSON representation can be easily parsed, and the data reused, further along the <a href="http://www.pipetree.com/qmacro/blog/2009/05/twitters-success/">pipeline</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pipetree.com/qmacro/blog/2009/08/coffeeshop-screencast-http-conneg-resource-representations-and-json/feed/</wfw:commentRss>
		</item>
		<item>
		<title>2nd coffeeshop REST/HTTP screencast</title>
		<link>http://www.pipetree.com/qmacro/blog/2009/08/2nd-coffeeshop-resthttp-screencast/</link>
		<comments>http://www.pipetree.com/qmacro/blog/2009/08/2nd-coffeeshop-resthttp-screencast/#comments</comments>
		<pubDate>Wed, 19 Aug 2009 19:10:56 +0000</pubDate>
		<dc:creator>dj</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[appengine]]></category>

		<category><![CDATA[coffeeshop]]></category>

		<category><![CDATA[http]]></category>

		<category><![CDATA[perl]]></category>

		<category><![CDATA[postbin]]></category>

		<category><![CDATA[pubsub]]></category>

		<category><![CDATA[rest]]></category>

		<guid isPermaLink="false">http://www.pipetree.com/qmacro/blog/?p=709</guid>
		<description><![CDATA[To follow on from the first coffeeshop demo screencast, I thought I&#8217;d make another. This time it&#8217;s to highlight the fact that coffeeshop is fundamentally a REST-orientated, HTTP-based pubsub application at the core, and not just a web-based application. Hopefully this comes across through the use of command-line HTTP tools to manipulate Channel, Subscriber and [...]]]></description>
			<content:encoded><![CDATA[<p>To follow on from the <a href="http://www.pipetree.com/qmacro/blog/2009/07/first-coffeeshop-demo-screencast/">first coffeeshop demo screencast</a>, I thought I&#8217;d make another. This time it&#8217;s to highlight the fact that <a href="http://wiki.github.com/qmacro/coffeeshop">coffeeshop</a> is fundamentally a REST-orientated, HTTP-based pubsub application at the core, and not just a web-based application. Hopefully this comes across through the use of command-line HTTP tools to manipulate Channel, Subscriber and Message resources.</p>
<p>This time, the <a href="http://wiki.github.com/qmacro/coffeeshop">coffeeshop</a> instance I&#8217;m using is one running on Google&#8217;s <a href="http://code.google.com/appengine/">App Engine</a> cloud infrastructure &#8212; on <a href="http://appgallery.appspot.com/">appspot.com</a>.</p>
<p><object width="560" height="340" data="http://www.youtube.com/v/TI48cdpWOBg&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/TI48cdpWOBg&amp;hl=en&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /></object></p>
<p><a href="http://www.youtube.com/watch?v=TI48cdpWOBg">http://www.youtube.com/watch?v=TI48cdpWOBg</a></p>
<p>In the screencast, I also make use of <a href="http://progrium.com/">Jeff Lindsay</a>&#8217;s great <a href="http://www.postbin.org/">Postbin</a> tool for creating the recipient resources for the Subscribers. It was originally created to help debug <a href="http://blog.webhooks.org/">Webhooks</a>, but of course, a Subscriber is a sort of Webhook as well. (Postbin runs on App Engine too!).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pipetree.com/qmacro/blog/2009/08/2nd-coffeeshop-resthttp-screencast/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Google Wave, XMPP and complexity</title>
		<link>http://www.pipetree.com/qmacro/blog/2009/08/google-wave-xmpp-and-complexity/</link>
		<comments>http://www.pipetree.com/qmacro/blog/2009/08/google-wave-xmpp-and-complexity/#comments</comments>
		<pubDate>Sun, 09 Aug 2009 19:50:18 +0000</pubDate>
		<dc:creator>dj</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[http]]></category>

		<category><![CDATA[jabber]]></category>

		<category><![CDATA[sendmail]]></category>

		<category><![CDATA[wave]]></category>

		<category><![CDATA[xmpp]]></category>

		<guid isPermaLink="false">http://www.pipetree.com/qmacro/blog/?p=701</guid>
		<description><![CDATA[Anil Dash provides food for thought in his post &#8220;What Works: The Web Way vs The Wave Way&#8220;. While I agree with him on the importance of the incremental approach to technology progression on the web (&#8221;The Web Way&#8221;), I do profess to have an intense interest in the pollination of XMPP into the HTTP [...]]]></description>
			<content:encoded><![CDATA[<p>Anil Dash provides food for thought in his post &#8220;<a href="http://dashes.com/anil/2009/08/what-works-the-web-way-vs-the-wave-way.html">What Works: The Web Way vs The Wave Way</a>&#8220;. While I agree with him on the importance of the incremental approach to technology progression on the web (&#8221;The Web Way&#8221;), I do profess to have an intense interest in the pollination of XMPP into the HTTP space.</p>
<p>However, I must call him on this small statement:</p>
<blockquote><p>&#8220;<span class="caps">XMPP </span>is way too complicated for any normal human to deploy&#8221;</p></blockquote>
<p>Compared to what? I&#8217;m getting the idea that he&#8217;s referring to &#8217;simpler&#8217; mechanisms such as HTTP or SMTP servers. Simpler? Has Anil modified a sendmail config file recently?</p>
<p>These days setting up an XMPP server is pretty straightforward. Then again, I am perhaps somewhat <a href="http://oreilly.com/catalog/9780596002022/">biased</a> <img src='http://www.pipetree.com/qmacro/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.pipetree.com/qmacro/blog/2009/08/google-wave-xmpp-and-complexity/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
