<?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>SheepDogInc.ca</title>
	<atom:link href="http://sheepdoginc.ca/feed/" rel="self" type="application/rss+xml" />
	<link>http://sheepdoginc.ca</link>
	<description>Canadian Google Apps Enterprise professional team</description>
	<lastBuildDate>Fri, 03 Feb 2012 19:15:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Writing Node.js modules</title>
		<link>http://sheepdoginc.ca/code-writing-node-js-modules/</link>
		<comments>http://sheepdoginc.ca/code-writing-node-js-modules/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 20:34:23 +0000</pubDate>
		<dc:creator>Honza Pokorny</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://sheepdoginc.ca/?p=1820</guid>
		<description><![CDATA[To say that node.js has enjoyed a great deal of positive publicity in the last few months would most certainly be an understatement. New node.js-related projects are popping up all over the place, and there seems to be this notion &#8230; <a href="http://sheepdoginc.ca/code-writing-node-js-modules/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>To say that node.js has enjoyed a great deal of positive publicity in the last<br />
few months would most certainly be an understatement. New node.js-related<br />
projects are popping up all over the place, and there seems to be this notion<br />
that if you aren&#8217;t using it you&#8217;re not cool enough.</p>
<p>Over the Christmas holidays, I sat down to sort out my photo library and I<br />
wanted to make a web photo gallery to share the images with family and friends.<br />
Being a mainly Python programmer, I wrote a Python script that will go through<br />
all of my photos and create smaller versions and thumbnails of the images that<br />
are suitable for the web. I think I have around 1500 images at the moment and<br />
it took a good 20 minutes to convert everything using Python Imaging Library.</p>
<p>I was rather frustrated with the performance. I think the reason for the<br />
slowness was the fact that the images were processed sequentially, one by one.<br />
What if I could modify my program to process more than one image at a time.<br />
This would certainly speed by the process. Then I thought about using threads<br />
in Python and I think I threw up in my mouth a little.</p>
<p>Then I remembered Node.js. It&#8217;s supposed to be all asynchronous and<br />
non-blocking. Perfect match. So I wrote a thumbnailer in node.</p>
<p>Essentially, it&#8217;s a worker queue that resizes images. You give it a source and<br />
destination directories and a number of workers and run it. The total time went<br />
from 20 minutes to 2 using about 5 workers. Much better, eh?</p>
<p>I decided to open source the project because I couldn&#8217;t find any node.js<br />
projects that do something even remotely similar. It&#8217;s called <a class="reference external" href="https://github.com/honza/node-thumbnail">node-thumbnail</a><br />
and you can find it on both Github and npmjs.</p>
]]></content:encoded>
			<wfw:commentRss>http://sheepdoginc.ca/code-writing-node-js-modules/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Freaky Friday</title>
		<link>http://sheepdoginc.ca/uncategorized-freaky-friday/</link>
		<comments>http://sheepdoginc.ca/uncategorized-freaky-friday/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 19:21:04 +0000</pubDate>
		<dc:creator>SheepDog feet on the street</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://sheepdoginc.ca/?p=1760</guid>
		<description><![CDATA[On Friday around here things got a little bit freaky geek style with SheepDoggers dressing up in their best costumes in support of one of the years greatest holidays!!! Staff around here look freaky at the best of times but &#8230; <a href="http://sheepdoginc.ca/uncategorized-freaky-friday/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>On Friday around here things got a little bit freaky geek style with SheepDoggers dressing up in their best costumes in support of one of the years greatest holidays!!! Staff around here look freaky at the best of times but check out the extra effort for Halloween!</p>
<p>&nbsp;</p>
<p><a href="http://sheepdoginc.ca/wp-content/uploads/2011/10/fembot.jpg"><img class="alignnone size-medium wp-image-1761" title="fembot" src="http://sheepdoginc.ca/wp-content/uploads/2011/10/fembot-225x300.jpg" alt="" width="225" height="300" /></a><a href="http://sheepdoginc.ca/wp-content/uploads/2011/10/The_Cupcake_Cowboy.jpg"></a></p>
<p><a href="http://sheepdoginc.ca/wp-content/uploads/2011/10/The_Cupcake_Cowboy.jpg"><img class="alignnone size-medium wp-image-1762" title="The_Cupcake_Cowboy" src="http://sheepdoginc.ca/wp-content/uploads/2011/10/The_Cupcake_Cowboy-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p><a href="http://sheepdoginc.ca/wp-content/uploads/2011/10/gTrax_pumpkin.jpg"><img class="alignnone size-medium wp-image-1763" title="gTrax_pumpkin" src="http://sheepdoginc.ca/wp-content/uploads/2011/10/gTrax_pumpkin-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p><a href="http://sheepdoginc.ca/wp-content/uploads/2011/10/kong2.jpg"><img class="alignnone size-medium wp-image-1769" title="kong2" src="http://sheepdoginc.ca/wp-content/uploads/2011/10/kong2-200x300.jpg" alt="" width="200" height="300" /></a></p>
<p><a href="http://sheepdoginc.ca/wp-content/uploads/2011/10/vader.jpg"><img class="alignnone size-medium wp-image-1772" title="vader" src="http://sheepdoginc.ca/wp-content/uploads/2011/10/vader-216x300.jpg" alt="" width="216" height="300" /></a></p>
<p><a href="http://sheepdoginc.ca/wp-content/uploads/2011/10/vamp.jpg"><img class="alignnone size-medium wp-image-1773" title="vamp" src="http://sheepdoginc.ca/wp-content/uploads/2011/10/vamp-200x300.jpg" alt="" width="200" height="300" /></a></p>
<p><a href="http://sheepdoginc.ca/wp-content/uploads/2011/10/arrrr.jpg"><img class="alignnone size-medium wp-image-1765" title="arrrr" src="http://sheepdoginc.ca/wp-content/uploads/2011/10/arrrr-200x300.jpg" alt="" width="200" height="300" /></a></p>
<p><a href="http://sheepdoginc.ca/wp-content/uploads/2011/10/bling.jpg"><img class="alignnone size-medium wp-image-1766" title="bling" src="http://sheepdoginc.ca/wp-content/uploads/2011/10/bling-200x300.jpg" alt="" width="200" height="300" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://sheepdoginc.ca/uncategorized-freaky-friday/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GoogleApps Customer Satisfaction Index released</title>
		<link>http://sheepdoginc.ca/uncategorized-googleapps-customer-satisfaction-index-released/</link>
		<comments>http://sheepdoginc.ca/uncategorized-googleapps-customer-satisfaction-index-released/#comments</comments>
		<pubDate>Thu, 20 Oct 2011 18:31:58 +0000</pubDate>
		<dc:creator>SheepDog feet on the street</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://sheepdoginc.ca/?p=1747</guid>
		<description><![CDATA[On October 15th, 2011, Google presented the Top 20 Global Partners with their results form a CSI polling of 233 Apps customers respond across ~20 top Apps MM/DSO partners globally. SheepDog is happy to announce their success across the board &#8230; <a href="http://sheepdoginc.ca/uncategorized-googleapps-customer-satisfaction-index-released/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>On October 15th, 2011, Google presented the Top 20 Global Partners with their results form a CSI polling of 233 Apps customers respond across ~20 top Apps MM/DSO partners globally. SheepDog is happy to announce their success across the board bringing a professional team to client GoogleApp and related cloud application deployments.</p>
<p>&nbsp;</p>
<p>The SheepDog Deployment team show consistent results above the average. Some specific highlights include:</p>
<p>&nbsp;</p>
<p>Overall client satisfaction with their reseller<br />
<span style="color: #ff6600;"><strong><span style="font-size: large;">SheepDog 92%</span></strong></span><br />
<span style="font-size: large;"><strong>Average 89%</strong></span></p>
<p>Clients likelihood to renew<br />
<span style="color: #ff6600;"><strong><span style="font-size: large;">SheepDog 96%</span></strong></span><br />
<span style="font-size: large;"><strong>Average 91%</strong></span></p>
<p>Professionalism<br />
<span style="color: #ff6600;"><strong><span style="font-size: large;">SheepDog 97%</span></strong></span><br />
<span style="font-size: large;"><strong>Average 93%</strong></span></p>
<p>Responsiveness<br />
<strong><span style="font-size: large; color: #ff6600;">SheepDog 94%</span></strong><br />
<span style="font-size: large;"><strong>Average 90%</strong></span></p>
<p>Technical ability<br />
<span style="font-size: large;"><strong><span style="color: #ff6600;">SheepDog 93%</span></strong></span><br />
<strong><span style="font-size: large;">Average 88%</span></strong></p>
<p>&nbsp;</p>
<p><strong><span style="font-size: large;"><span style="font-size: medium;">Congratulations to the SheepDog Deployment team and their continued focus on customer satisfaction.</span><br />
</span></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://sheepdoginc.ca/uncategorized-googleapps-customer-satisfaction-index-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DjangoCon US 2011</title>
		<link>http://sheepdoginc.ca/uncategorized-djangocon-us-2011/</link>
		<comments>http://sheepdoginc.ca/uncategorized-djangocon-us-2011/#comments</comments>
		<pubDate>Mon, 03 Oct 2011 12:06:48 +0000</pubDate>
		<dc:creator>Peter Darrow</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://sheepdoginc.ca/?p=1735</guid>
		<description><![CDATA[At SheepDog, we use the open-source Django Web framework on a large number of our projects. For the past three years, the Django community has hosted a conference for developers and users in Portland, Oregon. My co-worker Honza Pokorny and &#8230; <a href="http://sheepdoginc.ca/uncategorized-djangocon-us-2011/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>At SheepDog, we use the open-source <a href="http://www.djangoproject.com/">Django Web framework</a> on a large number of our projects. For the past three years, the Django community has hosted a conference for developers and users in Portland, Oregon. My co-worker Honza Pokorny and I were given the opportunity to attend <a href="http://djangocon.us/">this conference</a> last month and we had a blast. Here a few quick takeaways.</p>
<h3>Deploying Django</h3>
<p>Despite the Django official documentation&#8217;s recommendation to use Apache and mod_wsgi, most people seem to deploy Django with <a href="http://nginx.net/">nginx</a> and <a href="http://gunicorn.org/">gunicorn</a>. This was a pleasant surprise to us because we like the simplicity of this combination but thought it was less robust than Apache.</p>
<h3>Provisioning servers</h3>
<p>It seemed that everybody was talking about <a href="http://www.opscode.com/chef/">Chef</a> and automatic deployments. Instead of manually connecting to a server via ssh, you can run one command which will install all the necessary packages for your application (nginx, postgresql, etc.) and configure them. It makes the whole process less error-prone. Also, you&#8217;re more likely to spin up a new VM on your development machine to try things out on a production environment because you don&#8217;t have to think about setting it up. Especially with tools like <a href="http://vagrantup.com/">vagrant</a>, which automates the creation and provisioning of virtual machines, it&#8217;s dead easy.</p>
<h3>Pronouncing things</h3>
<p>When you read names of technical products, you can&#8217;t always be sure how they&#8217;re supposed to be pronounced. At a conference like DjangoCon, it becomes clear:</p>
<ul>
<li> PyPI: pie-pee-eye</li>
<li> PyPy: pie-pie</li>
<li> wsgi: wizz-gy</li>
<li> nginx: engine-x</li>
<li> gunicorn: gun-i-corn</li>
</ul>
<p>Did you go to DjangoCon US 2011? What are your thoughts?</p>
]]></content:encoded>
			<wfw:commentRss>http://sheepdoginc.ca/uncategorized-djangocon-us-2011/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Directory Harvest Attacks</title>
		<link>http://sheepdoginc.ca/uncategorized-directory-harvest-attacks/</link>
		<comments>http://sheepdoginc.ca/uncategorized-directory-harvest-attacks/#comments</comments>
		<pubDate>Tue, 02 Aug 2011 15:32:44 +0000</pubDate>
		<dc:creator>SheepDog feet on the street</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://sheepdoginc.ca/?p=1616</guid>
		<description><![CDATA[Written by SheepDog Senior Technician, Bruce Cooper. Recently, one of our client domains came under a substantial Directory Harvest Attack (DHA). Spammers increasingly are probing domain email systems in an attempt to identify and “harvest” legitimate email addresses from your &#8230; <a href="http://sheepdoginc.ca/uncategorized-directory-harvest-attacks/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Written by SheepDog Senior Technician, Bruce Cooper.</p>
<p>Recently, one of our client domains came under a substantial Directory Harvest Attack (DHA). Spammers increasingly are probing domain email systems in an attempt to identify and “harvest” legitimate email addresses from your organization. When they obtain lists of valid email addresses, they then compile them into lists that are sold  or distributed to other spammers. Postini has indicated that the number of directory harvest attacks has nearly doubled in the past six months.</p>
<p>If your mail server is MS Exchange or Domino Lotus Notes, a harvest attack, can literally slow your mail server down to a crawl or in some cases, result in server crashes and database corruption.</p>
<p>Fortunately our client is on Google Apps and has Postini Message Security in place. The sustained harvest attack did not stop their mail flow and they were able to continue on with their daily work flow. Postini’s exclusive Preemptive Email Protection technology (preEMPT) is able to identify and block DHAs at the SMTP connection level, prior to content filtering, and ensures that none of these types of attacks reaches the enterprise email gateway.</p>
<p>Postini effectively prevents the directory harvest attack from overloading your mail servers and stealing addresses from your email directory. It also stops spammers from using addresses that would have been harvested to further flood your email system with unwanted messages. It saves your email infrastructure from wasting cycles and bandwidth responding to directory harvest attacks and probes and reduces the costs and workload of your IT staff since it requires to integration with existing email infrastructure, no software and no hardware.<br />
If you are not using Postini Message Security we encourage you to review a Postini White Paper entitled <a href="http://www.postini.com/services/dha_wp.pdf">“The Silent Killer: How spammers are stealing your email directory”</a></p>
<p><a href="www.postini.com/services/dha_wp.pdf" class="broken_link"></p>
<p></a></p>
]]></content:encoded>
			<wfw:commentRss>http://sheepdoginc.ca/uncategorized-directory-harvest-attacks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction to Backbone.js</title>
		<link>http://sheepdoginc.ca/code-introduction-to-backbone-js/</link>
		<comments>http://sheepdoginc.ca/code-introduction-to-backbone-js/#comments</comments>
		<pubDate>Wed, 29 Jun 2011 19:40:26 +0000</pubDate>
		<dc:creator>Honza Pokorny</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://sheepdoginc.ca/?p=1418</guid>
		<description><![CDATA[Backbone.js is an exciting open source project that has been gaining popularity over the last few months. It&#8217;s a Javascript framework to help you build complex applications that run in the browser. In this post, we&#8217;ll walk through some of &#8230; <a href="http://sheepdoginc.ca/code-introduction-to-backbone-js/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://documentcloud.github.com/backbone/">Backbone.js</a> is an exciting open source project that has been gaining popularity over the last few months. It&#8217;s a Javascript framework to help you build complex applications that run in the browser. In this post, we&#8217;ll walk through some of the things Backbone is trying to solve and how to use it.</p>
<h2>The problem</h2>
<p>When you are developing a large Javascript application and you are using jQuery, your code tends to get disorganized very quickly. The script files are full of spaghetti code, endless callbacks and unrelated helper functions. The Backbone documentation puts it this way:</p>
<blockquote>
<p>When working on a web application that involves a lot of JavaScript, one of the first things you learn is to stop tying your data to the DOM. It&#8217;s all too easy to create JavaScript applications that end up as tangled piles of jQuery selectors and callbacks, all trying frantically to keep data in sync between the HTML UI, your JavaScript logic, and the database on your server. For rich client-side applications, a more structured approach is helpful.</p>
</blockquote>
<p>Backbone is trying to be that more <em>helpful</em> approach. Backbone is a Model-View-Controller framework that will hopefully add some structure to your project.</p>
<h2>Models</h2>
<p>In Backbone, Models are used to hold units of data. For example, here we create a simple <code>Post</code> class that will hold information about a blog post.</p>
<pre><code>var Post = Backbone.Model.extend({
  initialize: function() {
    if (!this.get('title'))
      this.set('title', 'Untitled');
  }
});
</code></pre>
<p>Models have a constructor method and some basic helper methods. They can perform validation, load data from a remote server, save changes to a database and more. Behind the scenes, Backbone serializes your models to and from JSON.</p>
<h2>Views</h2>
<p>Backbone uses Views to represent a Model instance in the DOM. A view usually contains a model and provides hooks to interact with the model through standard browser events such as click,, focus or hover.</p>
<pre><code>var PostView = Backbone.View.extend({
  events: {
    "h1 click": "titleClick"
  },

  initialize: function() {
    _.bindAll(this, 'render');
  },

  titleClick: function() {
  },
  render: function() {
  }

});
</code></pre>
<p>Each view instance knows how to render itself and it knows how to respond to predefined events. Here, we listen for clicks on the <code>H1</code> tag.</p>
<h2>Collections</h2>
<p>Collections are arrays of model instances. They allow you to quickly perform operations on a group of model instances. This is useful for things like filtering, sorting or batch deleting of items.</p>
<h2>Syncing</h2>
<p>Backbone exposes a syncing interface. This allows you to completely customize the way that your data is transmitted between the server and the client. Perhaps, you prefer XML over JSON. Or, instead of saving your data on a server, you can save it in HTML5 localStorage.</p>
<h2>From experience</h2>
<p>When I first looked at Backbone, it seemed easy and straight-forward.  However, when I went to build something with it I quickly realized it wasn&#8217;t as easy. Once you manage to put all the pieces together, it makes perfect sense. Reading through the examples and looking at some existing applications will help you a lot. Having wrapped my head around the key concepts, I was ready to build a complex app with no problems.</p>
<h2>Next?</h2>
<p>If you are interested in learning more about Backbone, be sure to check out the official documentation. I have also put together a small, proof-of-concept application for you to check out. It&#8217;s a simple <a href="http://honza.github.com/finances.js/">expense manager</a> and the source is on <a href="http://github.com/honza/finances.js">Github</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://sheepdoginc.ca/code-introduction-to-backbone-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Puzzle of the Fortnight</title>
		<link>http://sheepdoginc.ca/uncategorized-puzzle-of-the-fortnight-2/</link>
		<comments>http://sheepdoginc.ca/uncategorized-puzzle-of-the-fortnight-2/#comments</comments>
		<pubDate>Tue, 28 Jun 2011 11:30:34 +0000</pubDate>
		<dc:creator>David Wolfe</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://sheepdoginc.ca/?p=1397</guid>
		<description><![CDATA[My 10-year old daughter, Lila, came up with this puzzle.  A grade school class is given a problem of the form __ op __ op __ where there are two operations (ops) and three integers in the blanks.  They are &#8230; <a href="http://sheepdoginc.ca/uncategorized-puzzle-of-the-fortnight-2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<div>
<p>My 10-year old daughter, Lila, came up with this puzzle.  A grade school class is given a problem of the form</p>
<p style="padding-left: 30px;">__ op __ op __</p>
<p>where there are two operations (ops) and three integers in the blanks.  They are asked to compute the answer.  Some of the students got the correct answer of 9.  However, some of the students did not remember their order of operations and consequently got the incorrect answer of 12.  What was the question?  I.e., what numbers were in the blanks and what were the operations?</p>
<p>There is more than one solution to the puzzle.  Can you find all of them?</p>
<p>(<span style="text-decoration: underline;"><strong>Spoiler</strong></span>) The last puzzle was:</p>
<p>What do the following to two very distinctive sentences have in common?</p>
<ul>
<li>THE WORKERS SUPPLY POLISH FURNITURE.</li>
<li>BOB&#8217;S EVENING PROCEEDS FAIRLY.</li>
</ul>
<p>They actually have quite a lot in common.  Both sentences can be pronounced two different ways, yielding two completely different parses of the sentence.  There are two words in each sentence whose pronunciation and grammatical parts of speech change.  For the first, supply is an alternate spelling of supplely.  For the second, Bob could be divying up the ante fairly.</p>
<p>&nbsp;</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://sheepdoginc.ca/uncategorized-puzzle-of-the-fortnight-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Event Logging in Google AppEngine</title>
		<link>http://sheepdoginc.ca/code-event-logging-in-google-appengine/</link>
		<comments>http://sheepdoginc.ca/code-event-logging-in-google-appengine/#comments</comments>
		<pubDate>Fri, 24 Jun 2011 14:40:51 +0000</pubDate>
		<dc:creator>Christopher Troup</dc:creator>
				<category><![CDATA[AppEngine]]></category>
		<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://sheepdoginc.ca/?p=1373</guid>
		<description><![CDATA[Deployment to production systems is hard. No matter how many unit tests, QA processes and eyes you have on a project it is inevitable that someday, at some time, a bug will slip through. Companies like Facebook spend a lot &#8230; <a href="http://sheepdoginc.ca/code-event-logging-in-google-appengine/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/SheepDogInc/gae-event-logger"><img class="alignright size-full wp-image-1384" style="float: right; margin: 0 0 8px 24px;" title="Screen shot 2011-06-24 at 11.37.50 AM" src="http://sheepdoginc.ca/wp-content/uploads/2011/06/Screen-shot-2011-06-24-at-11.37.50-AM.png" alt="" width="131" height="40" /></a>Deployment to production systems is hard. No matter how many unit tests, QA processes and eyes you have on a project it is inevitable that someday, at some time, a bug will slip through. Companies like Facebook spend <a href="http://www.facebook.com/video/video.php?v=10100259101684977">a lot of time trying to catch these bugs</a> as soon as possible. One of the ways that this can be done is looking at pre-deployment and post-deployment event metrics, to see if spikes in errors correspond to fresh code being deployed.</p>
<p>Tools like <a href="http://graphite.wikidot.com/">Graphite</a> are great when you are in total control of the hosting environment &#8212; which unfortunately is not the case with Google AppEngine. So, to this end we built our own tool which emulates the parts of Graphite that are important to us. We&#8217;ve been using it in production on <a href="http://www.gtraxapp.com/">gTrax</a> for a while now, and its finally time for it to be open-sourced.</p>
<p>The tool is <strong><a href="https://github.com/SheepDogInc/gae-event-logger">gae-event-logger</a></strong> and is available for download on our GitHub page. Event Logger has minimal set up (no database configuration, etc.) and uses memcache to handle its data. Using memcache has its advantages because of the speed that we can log at without seeing any performance degradation. The last thing you want to do is have developers afraid to actually use logging for fear that it could slow down your site! However, being backed by memcache means that we have no guarantees that data actually sticks around &#8212; if Google flushes memcache then the statistics are dropped. In practice however, this is pretty rare.</p>
<p>A live example of its output is below, and captures the success/failure rate of certain RPC calls made from the gTrax application. If we start to see spikes of rpc.failure events we know something wrong has happend! We have dozens (hundreds!?) of graphs like this that we monitor &#8212; everything from login success rates to user signups.</p>
<p>&nbsp;</p>
<p><img src="http://app.gtraxapp.com/eventimager?series=rpc.success:rpc.failure" alt="" width="600" height="200" /></p>
<p>&nbsp;</p>
<p>Let us know if you use Event Logger in a project!</p>
]]></content:encoded>
			<wfw:commentRss>http://sheepdoginc.ca/code-event-logging-in-google-appengine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Integrating Get Satisfaction and GWT</title>
		<link>http://sheepdoginc.ca/gwt-integrating-get-satisfaction-and-gwt/</link>
		<comments>http://sheepdoginc.ca/gwt-integrating-get-satisfaction-and-gwt/#comments</comments>
		<pubDate>Thu, 23 Jun 2011 05:31:54 +0000</pubDate>
		<dc:creator>Christopher Troup</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[GWT]]></category>

		<guid isPermaLink="false">http://sheepdoginc.ca/?p=1350</guid>
		<description><![CDATA[If you’re using Get Satisfaction to manage customer relationships and support you’ll eventually want to provide deeper integration between your application and the Get Satisfaction support site. One common use case is to want to display updates from the GSFN &#8230; <a href="http://sheepdoginc.ca/gwt-integrating-get-satisfaction-and-gwt/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you’re using Get Satisfaction to manage customer relationships and support you’ll eventually want to provide deeper integration between your application and the Get Satisfaction support site. One common use case is to want to display updates from the GSFN site inside your application.</p>
<p>Get Satisfaction has a RESTful API that can be used, however developers will immediately realize that calling an AJAX JSON feed from the client-side browser will fail because of Same Origin Policy restrictions in the browser. Fortunately, Get Satisfaction has an undocumented feature which will help us bypass the restriction in a clever, cross-browser way.</p>
<p>The idea is to make use of a callback function inside the feed. The usual feed without the callback (<a href="http://api.getsatisfaction.com/products/67315/topics.json?style=update&amp;limit=5&amp;product=sheepdoginc_gtrax&amp;sort=last_active_at">here</a>) looks pretty standard:</p>
<div id="gist-1040106" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="p">{</span></div><div class='line' id='LC2'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;data&quot;</span><span class="o">:</span> <span class="p">[</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;at_sfn&quot;</span><span class="o">:</span> <span class="s2">&quot;http://getsatisfaction.com/sheepdoginc/topics/weve_moved-1io2po&quot;</span><span class="p">,</span> </div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;author&quot;</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;at_sfn&quot;</span><span class="o">:</span> <span class="s2">&quot;http://getsatisfaction.com/people/john_2286285&quot;</span><span class="p">,</span> </div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;avatar&quot;</span><span class="o">:</span> <span class="s2">&quot;http://s3.amazonaws.com/satisfaction-production/public/uploaded_images/7552101/sprinkles_medium.jpg&quot;</span><span class="p">,</span> </div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;avatar_url_large&quot;</span><span class="o">:</span> <span class="s2">&quot;http://s3.amazonaws.com/satisfaction-production/public/uploaded_images/7552101/sprinkles_large.jpg&quot;</span><span class="p">,</span> </div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;avatar_url_medium&quot;</span><span class="o">:</span> <span class="s2">&quot;http://s3.amazonaws.com/satisfaction-production/public/uploaded_images/7552101/sprinkles_medium.jpg&quot;</span><span class="p">,</span> </div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;avatar_url_mini&quot;</span><span class="o">:</span> <span class="s2">&quot;http://s3.amazonaws.com/satisfaction-production/public/uploaded_images/7552101/sprinkles_mini.jpg&quot;</span><span class="p">,</span> </div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;avatar_url_small&quot;</span><span class="o">:</span> <span class="s2">&quot;http://s3.amazonaws.com/satisfaction-production/public/uploaded_images/7552101/sprinkles_small.jpg&quot;</span><span class="p">,</span> </div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;canonical_name&quot;</span><span class="o">:</span> <span class="s2">&quot;john_2286285&quot;</span><span class="p">,</span> </div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;champion&quot;</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> </div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;employee&quot;</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> </div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;id&quot;</span><span class="o">:</span> <span class="mi">2569575</span><span class="p">,</span> </div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;name&quot;</span><span class="o">:</span> <span class="s2">&quot;John Everick&quot;</span><span class="p">,</span> </div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;url&quot;</span><span class="o">:</span> <span class="s2">&quot;http://api.getsatisfaction.com/people/2569575&quot;</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">},</span> </div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;champion&quot;</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> </div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;company_id&quot;</span><span class="o">:</span> <span class="mi">81150</span><span class="p">,</span> </div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;content&quot;</span><span class="o">:</span> <span class="s2">&quot;We&#39;ve moved the community for gTrax to this new location. Please continue to give your feedback, ask questions and help one another out as we pop in and out to gather your ideas on how to improve gTrax and answer any questions you have.\r&lt;br /&gt;&lt;br /&gt;\nCheers!&quot;</span><span class="p">,</span> </div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;created_at&quot;</span><span class="o">:</span> <span class="s2">&quot;2011/06/16 14:52:20 +0000&quot;</span><span class="p">,</span> </div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;emotitag&quot;</span><span class="o">:</span> <span class="p">{</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;face&quot;</span><span class="o">:</span> <span class="s2">&quot;happy&quot;</span><span class="p">,</span> </div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;feeling&quot;</span><span class="o">:</span> <span class="s2">&quot;excited&quot;</span><span class="p">,</span> </div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;intensity&quot;</span><span class="o">:</span> <span class="mi">1</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">},</span> </div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;employee&quot;</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> </div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;flag_count&quot;</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> </div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;follower_count&quot;</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> </div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;has_promoted_replies&quot;</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span> </div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;id&quot;</span><span class="o">:</span> <span class="mi">2544294</span><span class="p">,</span> </div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;last_active_at&quot;</span><span class="o">:</span> <span class="s2">&quot;2011/06/16 14:52:20 +0000&quot;</span><span class="p">,</span> </div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;me_too_count&quot;</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> </div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;most_recent_activity&quot;</span><span class="o">:</span> <span class="s2">&quot;create&quot;</span><span class="p">,</span> </div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;reply_count&quot;</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span> </div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;slug&quot;</span><span class="o">:</span> <span class="s2">&quot;weve_moved-1io2po&quot;</span><span class="p">,</span> </div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;status&quot;</span><span class="o">:</span> <span class="s2">&quot;complete&quot;</span><span class="p">,</span> </div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;style&quot;</span><span class="o">:</span> <span class="s2">&quot;update&quot;</span><span class="p">,</span> </div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;subject&quot;</span><span class="o">:</span> <span class="s2">&quot;We&#39;ve Moved!&quot;</span><span class="p">,</span> </div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;url&quot;</span><span class="o">:</span> <span class="s2">&quot;http://api.getsatisfaction.com/topics/2544294&quot;</span><span class="p">,</span> </div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;user_defined_code&quot;</span><span class="o">:</span> <span class="kc">false</span></div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">],</span> </div><div class='line' id='LC45'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="s2">&quot;total&quot;</span><span class="o">:</span> <span class="mi">1</span></div><div class='line' id='LC46'><span class="p">}</span></div><div class='line' id='LC47'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1040106/751eef432189ebae8db690ed93c1da5040b9b1bf/gistfile1.json" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1040106#file_gistfile1.json" style="float:right;margin-right:10px;color:#666">gistfile1.json</a>
            <a href="https://gist.github.com/1040106">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Of course without a callback we won&#8217;t actually be able to use these results if they were fetched with AJAX. The argument we want to add is <strong>callback=gsUpdate</strong>. Adding the callback (<a href="http://api.getsatisfaction.com/products/67315/topics.json?style=update&amp;callback=gsUpdate&amp;limit=5&amp;product=sheepdoginc_gtrax&amp;sort=last_active_at">here</a>) argument to the GET string we get something a little more useful:</p>
<div id="gist-1040193" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>gsUpdate({&quot;data&quot;:[{&quot;me_too_count&quot;:1,&quot;status&quot;:&quot;complete&quot;,&quot;employee&quot;:true,&quot;follower_count&quot;:1,&quot;style&quot;:&quot;update&quot;,&quot;reply_count&quot;:0,&quot;slug&quot;:&quot;weve_moved-1io2po&quot;,&quot;last_active_at&quot;:&quot;2011/06/16 14:52:20 +0000&quot;,&quot;champion&quot;:false,&quot;has_promoted_replies&quot;:false,&quot;at_sfn&quot;:&quot;http://getsatisfaction.com/sheepdoginc/topics/weve_moved-1io2po&quot;,&quot;created_at&quot;:&quot;2011/06/16 14:52:20 +0000&quot;,&quot;most_recent_activity&quot;:&quot;create&quot;,&quot;subject&quot;:&quot;We've Moved!&quot;,&quot;emotitag&quot;:{&quot;feeling&quot;:&quot;excited&quot;,&quot;face&quot;:&quot;happy&quot;,&quot;intensity&quot;:1},&quot;company_id&quot;:81150,&quot;author&quot;:{&quot;avatar_url_large&quot;:&quot;http://s3.amazonaws.com/satisfaction-production/public/uploaded_images/7552101/sprinkles_large.jpg&quot;,&quot;employee&quot;:true,&quot;avatar_url_small&quot;:&quot;http://s3.amazonaws.com/satisfaction-production/public/uploaded_images/7552101/sprinkles_small.jpg&quot;,&quot;avatar_url_medium&quot;:&quot;http://s3.amazonaws.com/satisfaction-production/public/uploaded_images/7552101/sprinkles_medium.jpg&quot;,&quot;avatar_url_mini&quot;:&quot;http://s3.amazonaws.com/satisfaction-production/public/uploaded_images/7552101/sprinkles_mini.jpg&quot;,&quot;champion&quot;:false,&quot;at_sfn&quot;:&quot;http://getsatisfaction.com/people/john_2286285&quot;,&quot;canonical_name&quot;:&quot;john_2286285&quot;,&quot;name&quot;:&quot;John Everick&quot;,&quot;avatar&quot;:&quot;http://s3.amazonaws.com/satisfaction-production/public/uploaded_images/7552101/sprinkles_medium.jpg&quot;,&quot;url&quot;:&quot;http://api.getsatisfaction.com/people/2569575&quot;,&quot;id&quot;:2569575},&quot;flag_count&quot;:0,&quot;content&quot;:&quot;We've moved the community for gTrax to this new location. Please continue to give your feedback, ask questions and help one another out as we pop in and out to gather your ideas on how to improve gTrax and answer any questions you have.\r&lt;br /&gt;&lt;br /&gt;\nCheers!&quot;,&quot;url&quot;:&quot;http://api.getsatisfaction.com/topics/2544294&quot;,&quot;id&quot;:2544294,&quot;user_defined_code&quot;:false}],&quot;total&quot;:1})</div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1040193/0fba9f163852e9e8f030bbbae477d9a48183762f/gistfile1.js" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1040193#file_gistfile1.js" style="float:right;margin-right:10px;color:#666">gistfile1.js</a>
            <a href="https://gist.github.com/1040193">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Way better! The external GSFN API is now co-operating with us to provide something we can hook into to actually use the results inside our GWT application. We&#8217;ll need to use a bit of JSNI to provide the gsUpdate hook from the GWT application, and then post-process the results so that they can be displayed via GWT widgets.</p>
<p>In our widget we&#8217;ll do three things. First, we need to export the gsUpdate callback to the top-level window object so that the Get Satisfaction call can find it. We then want to grab the data out of the stream and pass it back into native GWT for processing. When we pass back into native GWT, it&#8217;d be nice to have a JavaScriptObject wrapper around the JS objects, so that we can use them without coupling too tightly to the JSON response object.</p>
<div id="gist-1040232" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="kn">import</span> <span class="nn">com.google.gwt.core.client.JavaScriptObject</span><span class="o">;</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">GSFNUpdateObject</span> <span class="kd">extends</span> <span class="n">JavaScriptObject</span> <span class="o">{</span></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="kd">protected</span> <span class="nf">GSFNUpdateObject</span><span class="o">()</span> <span class="o">{}</span></div><div class='line' id='LC5'>&nbsp;&nbsp;</div><div class='line' id='LC6'>&nbsp;&nbsp;<span class="kd">public</span> <span class="kd">final</span> <span class="kd">native</span> <span class="n">String</span> <span class="nf">getDate</span><span class="o">()</span> <span class="cm">/*-{</span></div><div class='line' id='LC7'><span class="cm">    return this.created_at;</span></div><div class='line' id='LC8'><span class="cm">  }-*/</span><span class="o">;</span></div><div class='line' id='LC9'>&nbsp;&nbsp;</div><div class='line' id='LC10'>&nbsp;&nbsp;<span class="kd">public</span> <span class="kd">final</span> <span class="kd">native</span> <span class="n">String</span> <span class="nf">getTitle</span><span class="o">()</span> <span class="cm">/*-{</span></div><div class='line' id='LC11'><span class="cm">    return this.subject;</span></div><div class='line' id='LC12'><span class="cm">  }-*/</span><span class="o">;</span></div><div class='line' id='LC13'>&nbsp;&nbsp;</div><div class='line' id='LC14'>&nbsp;&nbsp;<span class="kd">public</span> <span class="kd">final</span> <span class="kd">native</span> <span class="n">String</span> <span class="nf">getContent</span><span class="o">()</span> <span class="cm">/*-{</span></div><div class='line' id='LC15'><span class="cm">    return this.content;</span></div><div class='line' id='LC16'><span class="cm">  }-*/</span><span class="o">;</span></div><div class='line' id='LC17'>&nbsp;&nbsp;</div><div class='line' id='LC18'>&nbsp;&nbsp;<span class="kd">public</span> <span class="kd">final</span> <span class="kd">native</span> <span class="n">String</span> <span class="nf">getLink</span><span class="o">()</span> <span class="cm">/*-{</span></div><div class='line' id='LC19'><span class="cm">    return this.at_sfn;</span></div><div class='line' id='LC20'><span class="cm">  }-*/</span><span class="o">;</span></div><div class='line' id='LC21'>&nbsp;&nbsp;</div><div class='line' id='LC22'>&nbsp;&nbsp;<span class="kd">public</span> <span class="kd">final</span> <span class="kd">native</span> <span class="n">String</span> <span class="nf">getAuthorName</span><span class="o">()</span> <span class="cm">/*-{</span></div><div class='line' id='LC23'><span class="cm">    return this.author.name;</span></div><div class='line' id='LC24'><span class="cm">  }-*/</span><span class="o">;</span></div><div class='line' id='LC25'>&nbsp;&nbsp;</div><div class='line' id='LC26'>&nbsp;&nbsp;<span class="kd">public</span> <span class="kd">final</span> <span class="kd">native</span> <span class="n">String</span> <span class="nf">getAuthorAvatar</span><span class="o">()</span> <span class="cm">/*-{</span></div><div class='line' id='LC27'><span class="cm">    return this.author.avatar_url_medium;</span></div><div class='line' id='LC28'><span class="cm">  }-*/</span><span class="o">;</span></div><div class='line' id='LC29'><span class="o">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1040232/0b1108a8db7d81be452a272290f6e1ac27df8782/GSFNUpdateObject.java" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1040232#file_gsfn_update_object.java" style="float:right;margin-right:10px;color:#666">GSFNUpdateObject.java</a>
            <a href="https://gist.github.com/1040232">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="kd">class</span> <span class="nc">FancyWidget</span> <span class="kd">extends</span> <span class="n">Composite</span> <span class="o">{</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="kd">public</span> <span class="nf">FancyWidget</span><span class="o">()</span> <span class="o">{</span></div><div class='line' id='LC3'><br/></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">gsfnUpdate</span><span class="o">();</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">ScriptElement</span> <span class="n">el</span> <span class="o">=</span> <span class="n">Document</span><span class="o">.</span><span class="na">get</span><span class="o">().</span><span class="na">createScriptElement</span><span class="o">();</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">el</span><span class="o">.</span><span class="na">setLang</span><span class="o">(</span><span class="s">&quot;javascript&quot;</span><span class="o">);</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">el</span><span class="o">.</span><span class="na">setSrc</span><span class="o">(</span><span class="s">&quot;http://api.getsatisfaction.com/products/67315/topics.json?style=update&amp;callback=gsUpdate&amp;limit=5&amp;product=sheepdoginc_gtrax&amp;sort=last_active_at&quot;</span><span class="o">);</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">HeadElement</span> <span class="n">element</span> <span class="o">=</span> <span class="n">Document</span><span class="o">.</span><span class="na">get</span><span class="o">().</span><span class="na">getElementsByTagName</span><span class="o">(</span><span class="s">&quot;head&quot;</span><span class="o">).</span><span class="na">getItem</span><span class="o">(</span><span class="mi">0</span><span class="o">).</span><span class="na">cast</span><span class="o">();</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">element</span><span class="o">.</span><span class="na">appendChild</span><span class="o">(</span><span class="n">el</span><span class="o">);</span></div><div class='line' id='LC13'><br/></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">// ...</span></div><div class='line' id='LC15'>&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC16'><br/></div><div class='line' id='LC17'>&nbsp;&nbsp;<span class="kd">public</span> <span class="kt">void</span> <span class="nf">recieveUpdateList</span><span class="o">(</span><span class="n">JsArray</span><span class="o">&lt;</span><span class="n">GSFNUpdateObject</span><span class="o">&gt;</span> <span class="n">items</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">updates</span><span class="o">.</span><span class="na">clear</span><span class="o">();</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">items</span><span class="o">.</span><span class="na">length</span><span class="o">();</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">GSFNUpdateObject</span> <span class="n">item</span> <span class="o">=</span> <span class="n">items</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">);</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">updates</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="n">GSFNUpdateWidget</span><span class="o">(</span><span class="n">item</span><span class="o">));</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC24'>&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC25'><br/></div><div class='line' id='LC26'>&nbsp;&nbsp;<span class="kd">public</span> <span class="kd">native</span> <span class="kt">void</span> <span class="nf">gsfnUpdate</span><span class="o">()</span> <span class="cm">/*-{</span></div><div class='line' id='LC27'><span class="cm">		var reference = this;</span></div><div class='line' id='LC28'><span class="cm">		$wnd.gsUpdate = function(items) {</span></div><div class='line' id='LC29'><span class="cm">			reference.@your.namespace.FancyWidget::recieveUpdateList(Lcom/google/gwt/core/client/JsArray;)(items.data);</span></div><div class='line' id='LC30'><span class="cm">		}</span></div><div class='line' id='LC31'><span class="cm">  }-*/</span><span class="o">;</span></div><div class='line' id='LC32'><br/></div><div class='line' id='LC33'><span class="o">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1040232/e3f3831c0fcbc289f40ff34667dba98180fe0e95/gistfile1.java" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1040232#file_gistfile1.java" style="float:right;margin-right:10px;color:#666">gistfile1.java</a>
            <a href="https://gist.github.com/1040232">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>As you can see, the &lt;script&gt; tag is created and injected into the page load upon construction of the widget &#8212; from that point on there is a callback dance where results are fetched, processed and displayed.</p>
<p>The result is that the 5 most recent updates from Get Satisfaction are displayed &#8212; along with links back to Get Satisfaction for users to post questions, comments and ideas. You can format the results however you&#8217;d like, without relying on Get Satisfaction&#8217;s default widgets.</p>
<p>&nbsp;</p>
<p><a href="http://sheepdoginc.ca/wp-content/uploads/2011/06/Screen-shot-2011-06-22-at-11.47.54-AM.png"><img class="alignnone size-medium wp-image-1363" title="A GetSatisfaction Update" src="http://sheepdoginc.ca/wp-content/uploads/2011/06/Screen-shot-2011-06-22-at-11.47.54-AM-300x136.png" alt="" width="300" height="136" /></a></p>
<p>&nbsp;</p>
<p>Hopefully this will help you in integrating with Get Satisfaction when using GWT &#8212; and maybe provide strategies and ideas for other APIs that support callback arguments as well!</p>
]]></content:encoded>
			<wfw:commentRss>http://sheepdoginc.ca/gwt-integrating-get-satisfaction-and-gwt/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Nova Scotia Community College provides a multi-campus solution to its 55,000 users</title>
		<link>http://sheepdoginc.ca/uncategorized-nova-scotia-community-college-provides-a-multi-campus-solution-to-its-55000-users/</link>
		<comments>http://sheepdoginc.ca/uncategorized-nova-scotia-community-college-provides-a-multi-campus-solution-to-its-55000-users/#comments</comments>
		<pubDate>Wed, 22 Jun 2011 18:55:03 +0000</pubDate>
		<dc:creator>Heather Fraser</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://sheepdoginc.ca/?p=1366</guid>
		<description><![CDATA[Monday June 20, 2011 Posted by Wilson Verge, Director IT Services Department, NSCC Editors note: NSCC is at the forefront of education innovation in Canada with a committed focus on Learning, Capacity and the Future. Spread across 15 full-service campuses, &#8230; <a href="http://sheepdoginc.ca/uncategorized-nova-scotia-community-college-provides-a-multi-campus-solution-to-its-55000-users/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Monday June 20, 2011</p>
<p>Posted by Wilson Verge, Director IT Services Department, NSCC</p>
<p><strong><em>Editors note: NSCC is at the forefront of education innovation in Canada with a committed focus on Learning, Capacity and the Future. Spread across 15 full-service campuses, NSCC is the largest and most diverse institution in Nova Scotia. Driving sustainable building and technological practices, NSCC brings together trades and technologies to create change in the environments of the future.</em></strong></p>
<p>Ten years ago, the <a href="http://nscc.ca" target="_blank">Nova Scotia Community College</a> had a reputation for being a trade school with a stale brand and a lack of forward thinking. This type of brand has a hard time attracting a new generation of learners. There was a need for change and change they did. A decade later, NSCC is the most innovative and forward thinking institution in eastern Canada with a new roster of courses and programs focusing on producing the thought and technical leaders of the future. So, what better place to access the innovation of Google Apps for Education&#8230;enter Wilson Verge, NSCCs Director of IT Services Department and project Champion.</p>
<p>Wilson heads up the NSCC IT department which supports 55,000 users divided into student, faculty, staff and alumni user groups spread across campuses in fifteen towns and cities in Nova Scotia, Canada. To add to the complexity, NSCC’s legacy IT infrastructure was supporting a hybrid IT solution made up of several different versions of Microsoft Outlook. Seeing the need to mirror the College’s commitment to innovation in their IT environment, Wilson worked with <a href="http://sheepdoginc.ca">Google’s Premier Canadian Partner, SheepDogInc</a> to evaluate and eventually deploy Google Apps for Education as their perfect match. The maturity and robustness of the Google Apps for Education products were a deciding factor for the College who had many stakeholders to convince when making the decision to shift to a new messaging and collaboration platform.</p>
<p>Identifying change management as a critical point of failure, NSCC and SheepDog instituted a steering committee who conducted focus groups and user surveys as the first phase of the project allowing the College to gain acceptance in their stakeholder groups. Access to the <a href="http://edu.googleapps.com/" target="_blank">marketing and change management support offered by Google</a> helped seal the deal and lead the implementation of the solution to 22,000 users institution wide (with the additional 33,000 alumni to follow).</p>
<p>&nbsp;</p>
<p>In addition to the many features that the Google Apps for Education offers users and administrators, there are two main differentiating points from the legacy Microsoft systems. The first is the seamless document collaboration of users, particularly staff in various campuses, allowing for up-to-date documentation and an end to version control. The second is the integration of a single sign on solution with the NSCC student portal and the active directory linked to Google Apps, which provides a successful solution for identity management not available in the past. Now up and running, NSCC is benefiting from the features the students and staff access in their lives outside the EDU space and productivity is at an all time high while the IT department can finally effectively track and manage user IDs.</p>
<p>&nbsp;</p>
<p>The next step of innovation for the NSCC is anyone&#8217;s guess but their eyes have been opened to the potential of the Google Apps and the platform beneath. Discussions have started between the S<a href="http://sheepdoginc.ca/software/" target="_blank">heepDog software engineering division</a> and the <a href="http://www.nscc.ca/learning_programs/programs/PlanDescr.aspx?prg=GEOS&amp;pln=GISTECHNO" target="_blank">NSCC Geographic Information Systems (GIS) department</a>. Stay tuned to see how these leaders of the future will leverage Google in one of the fastest growing technology sectors in the world.</p>
]]></content:encoded>
			<wfw:commentRss>http://sheepdoginc.ca/uncategorized-nova-scotia-community-college-provides-a-multi-campus-solution-to-its-55000-users/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

