<?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>Cantina Consulting</title>
	<atom:link href="http://www.cantinaconsulting.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cantinaconsulting.com</link>
	<description></description>
	<lastBuildDate>Tue, 27 Jul 2010 18:47:36 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Automating Android Builds: Part I</title>
		<link>http://www.cantinaconsulting.com/2010/07/26/automating-android-builds-part-i/</link>
		<comments>http://www.cantinaconsulting.com/2010/07/26/automating-android-builds-part-i/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 03:20:20 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Mobile]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=486</guid>
		<description><![CDATA[﻿The Android platform provides a great way to deliver rich and highly functional native mobile applications to an ever growing number of smartphone and tablet devices, and soon even your TV. With this platform comes a rich set of development tools, primarily based around the Eclipse development environment, but which also includes command line tools [...]]]></description>
			<content:encoded><![CDATA[<p>﻿The Android platform provides a great way to deliver rich and highly functional native mobile applications to an ever growing number of smartphone and tablet devices, and soon even your TV. With this platform comes a rich set of development tools, primarily based around the Eclipse development environment, but which also includes command line tools for packaging, installing, and debugging Android applications, as well as helper tasks for Apache Ant which is used for build automation for many enterprise Java projects.</p>
<p>Most development teams working on complex projects in this day and age are going to employ some combination of generally accepted best practices in software engineering to ensure consistency in build quality, automate complex build processes, and automate unit and functional testing to continually ensure quality as development progresses.  Such practices include:</p>
<ul>
<li>Automated unit, integration, and functional testing (faciliated by tools such as <a href="http://www.junit.org/">JUnit</a> and <a href="http://seleniumhq.org/">Selenium</a>)</li>
<li>Build automation (using tools like <a href="http://ant.apache.org/">Ant</a> and <a href="http://maven.apache.org/">Maven</a>)</li>
<li>Continuous build integration (to ensure build quality and identify conflicts early)</li>
<li>Code coverage analysis (measuring how much of your application you&#8217;ve tested)</li>
<li>Static code analysis (find common coding errors with tools such as <a href="http://findbugs.sourceforge.net/">FindBugs</a>)</li>
</ul>
<p>It is reasonable to assume that a complex Android application would benefit from these practices, especially with a larger development team.</p>
<p>Android provides most of the necessary integration points and tools to implement many of the best practices mentioned above, and allows for automating the several steps required to build an Android application.  However, despite this, there are some key lessons to learn that to learn that separate an Android build process from other Java-based projects.</p>
<h2>﻿Java is not Java</h2>
<p>First off, let&#8217;s get one thing straight.  The Java classes that one writes to implement an Android application compile to the Dalvik VM, not the Java Virtual Machine provided by Sun (now Oracle).  The engineers building the Android platform chose a separate virtual machine implementation for a <a href="http://www.betaversion.org/~stefano/linotype/news/110/">variety of reasons</a>, but it is arguably the need to <a href="http://www.ctoedge.com/content/how-dalvik-virtual-machine-works-google-android">slim down and tailor a VM for use on a mobile device</a>, which has very hard limitations on processor resources and memory, that lead to this decision.</p>
<p>Because of the separate VM implementation, the full set of standard <a href="http://java.sun.com/javase/6/docs/api/">Java SE classes</a> is not available.  The Android team has provided a workable subset of the Java SE API with a few notable additions to assist in such things as managing HTTP communication, parsing JSON, and parsing XML.  This distinction leads to one very important point:</p>
<p><em>Not all Java targeted for the Sun JVM will run in Android. </em></p>
<p>This is important to note when planning to use 3rd party libraries in an Android application that were not targeted for Android.  While many 3rd party JARs can be included in Android projects, many cannot.  Clearly if the dependencies can be met with the pared down API, the JAR will not work.</p>
<h3>Running It</h3>
<p>The APIs provided by Android&#8217;s augmented subset of the Java SE API are exposed to developer projects (primarily in Eclipse) via the android.jar file.  This JAR provides the interfaces for the Android API, but none of the implementation code.</p>
<p><em>Why the limitation?</em></p>
<p>Classes compiled for the Dalvik VM aren&#8217;t executed in their .class file bytecode form, but rather must be converted to Dalvik&#8217;s Executable format, or dex.  According to <a href="http://developer.android.com/guide/basics/what-is-android.html">this Android page</a>, dex is optimized for a smaller memory footprint, and also to allow multiple VMs to execute efficiently.</p>
<p>What this means for the average developer is that you cannot go to your trusty Eclipse Run As &gt; JUnit Test menu item and fire off unit tests.  All Java code targeted for Android must run within the Android execution environment, compiled as .dex files, in the Dalvik VM.  Without the implementation classes for android.jar being in standard JAR format (they&#8217;re buried in .dex files in Android), the best options for running your code during development is either:</p>
<ul>
<li>Plugging in your favorite Android phone via USB debugging or</li>
<li>Running your code in an Android emulator</li>
</ul>
<p>While there are ways to run the <a href="http://www.netmite.com/android/mydroid/2.0/dalvik/docs/hello-world.html">Dalvik VM on the desktop</a>, those methods are not yet integrated into the Android standard toolchain.</p>
<h2>Emulating Success</h2>
<p>The Android SDK provides a rich set of tools for creating, launching, customizing, and debugging emulated Android devices, known as <a href="http://developer.android.com/guide/developing/tools/emulator.html">Android Virtual Devices</a> (AVDs).  These emulator instances can model different hardware configurations as well as different target Android OS versions, which is useful for testing an application across the many <a href="http://developer.android.com/resources/dashboard/platform-versions.html">deployed versions of Android</a> that exist on the many Android devices that exist today.</p>
<p>The Android emulator, based on <a href="http://wiki.qemu.org/Main_Page">QEMU</a>, provides emulated versions of many of the hardware features commonly found on Android devices (from the Android Developer Center):</p>
<ul>
<li>An ARMv5 CPU and the corresponding memory-management unit (MMU)</li>
<li>A 16-bit LCD display</li>
<li>One or more keyboards (a Qwerty-based keyboard and associated Dpad/Phone buttons)</li>
<li>A sound chip with output and input capabilities</li>
<li>Flash memory partitions (emulated through disk image files on the development machine)</li>
<li>A GSM modem, including a simulated SIM Card</li>
</ul>
<div>While this represents a common set of hardware features, it does not provide the following (from <a href="http://developer.android.com/guide/developing/tools/emulator.html#limitations">here</a>):</div>
<div>
<div>
<ul>
<li>No support for placing or receiving actual phone calls. You can simulate phone calls (placed and received) through the emulator console, however.</li>
<li>No support for USB connections</li>
<li>No support for camera/video capture (input).</li>
<li>No support for device-attached headphones</li>
<li>No support for determining connected state</li>
<li>No support for determining battery charge level and AC charging state</li>
<li>No support for determining SD card insert/eject</li>
<li>No support for Bluetooth</li>
</ul>
<p>Beyond these official limitations, I&#8217;ve found a few more.  The emulator is often quite slow.  I haven&#8217;t spent the time to quantify this but it is slow in a few key areas.</p>
<p>The time to startup a &#8220;fresh&#8221; emulator is often too long for casual unit tests, upwards of several minutes, which is why the Android Eclipse tools allows the user to keep an emulator running between test runs.  This will have impact on our testing automation in the upcoming Part II of this article.</p>
</div>
</div>
<p>The slowness is evident elsewhere.  It is a generally held belief that the emulator does not adequately support video playback, and my experience in building custom video players in Android supports this.  Playback often does not come close to the video frame rate, therefore video playback testing is best handled on a physical device via USB debugging.  Given that it is difficult to automate testing around video playback, this is less of a concern, however it is important to note when setting up a QA team for playback testing.  Real devices should be available for QA as the emulator will likely not suffice.</p>
<h2>Up Next</h2>
<p>This is just a taste of some of the relevant architectural details of the Android platform that affect build automation.  In the next installment, I&#8217;ll dig deeper into build configuration, automating tests and managing the emulator from Ant.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2010/07/26/automating-android-builds-part-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The World Cup of Online Video &#8211; what does it mean?</title>
		<link>http://www.cantinaconsulting.com/2010/07/23/the-world-cup-of-online-video-what-does-it-mean/</link>
		<comments>http://www.cantinaconsulting.com/2010/07/23/the-world-cup-of-online-video-what-does-it-mean/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 13:03:05 +0000</pubDate>
		<dc:creator>alec</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[engagement]]></category>
		<category><![CDATA[interactivity]]></category>
		<category><![CDATA[online video]]></category>
		<category><![CDATA[social networking]]></category>
		<category><![CDATA[world cup]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=478</guid>
		<description><![CDATA[Well, the stats are in, and it&#8217;s official. The World Cup &#8211; considered by many to be the largest, most watched sporting event in the world &#8211; did in fact post the largest online video viewing numbers of all time as measured by a whole host of outlets and measurement services. Big deal, right? It&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>Well, the stats are in, and it&#8217;s official. The World Cup &#8211; considered by many to be the largest, most watched sporting event in the world &#8211; did in fact post the largest online video viewing numbers of all time as measured by a <a href="http://http://newteevee.com/2010/07/13/world-cup-stats-the-nets-biggest-sporting-event/">whole host of outlets and measurement services</a>. Big deal, right? It&#8217;s a no brainer that we&#8217;d see such staggering numbers for the World Cup &#8211; I mean, it&#8217;s the bloody World Cup! One of a handful of events in our globalized, 24/7 media input world that can still rally that kind of focus and participation. So &#8211; yea &#8211; it&#8217;s no surprise we broke records for online viewership. Why should we care anyway? And what does this mean about how our companies and organizations should be thinking about online video now and in the immediate future?</p>
<p>The main reason why I cared is not because I&#8217;m a diehard soccer fan, but because we just expected to be able to watch the games. Live. Wherever we were at that moment. In good quality. With good audio (vuvuzelas notwithstanding). And a host of other features to keep us interested. And we did. Online. Over the phone. It&#8217;s amazing how quickly we&#8217;ve come to expect that we can consume a live event of the magnitude of the World Cup online. I mean &#8211; that is cool.</p>
<p>But does it matter to your business? How does this relate at all? In some ways, of course, it doesn&#8217;t. Sports have been a driver for many of the mega-events in recent online video history, primarily due to the nature of the events themselves. But outside of the media world &#8211; what does this mean for your online video strategy:</p>
<p><strong>Go global</strong>. If your company has a global presence this event certainly confirmed what you may already know&#8230;.that audiences around the globe have the capability and desire to consume online video. But don&#8217;t just throw anything out there. Make sure you provide the proper translations and content to fit the needs of the region you are targeting.</p>
<p><strong>Interactivity = engagement</strong>. The majority of the implementations had a high level of interactive features woven into the experience. The ESPN3 player allowed the ability to switch between games, languages, get stats, chat with others. It&#8217;s not just about providing the moving pictures. The ability to customize players with interactive details and hot spots is growing quickly and provides many businesses with the ability to create more engagement and calls to action towards your ultimate business goal.</p>
<p><strong>Be where your users are.</strong> The success of online video with an event like the World Cup hinged directly on providing fans the ability to get their fix wherever they were &#8211; at work, on the road, at home. This means thinking not just about video on your website but also how to syndicate your assets externally and how you might leverage mobile platforms to deliver your message to your users.</p>
<p> </p>
<p> </p>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2010/07/23/the-world-cup-of-online-video-what-does-it-mean/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sprinting with Rails 3</title>
		<link>http://www.cantinaconsulting.com/2010/07/20/sprinting-with-rails-3/</link>
		<comments>http://www.cantinaconsulting.com/2010/07/20/sprinting-with-rails-3/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 14:28:50 +0000</pubDate>
		<dc:creator>mattv</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=446</guid>
		<description><![CDATA[I love Ruby on Rails.  There are few things in life that bring me more joy than opening up Textmate and coding a Rails web app.   That being said, my infatuation has been with Rails 2, and I&#8217;ve been itching to get working with Rails 3 &#8211; especially with the prospect of a release [...]]]></description>
			<content:encoded><![CDATA[<p>I love Ruby on Rails.  There are few things in life that bring me more joy than opening up Textmate and coding a Rails web app.   That being said, my infatuation has been with Rails 2, and I&#8217;ve been itching to get working with Rails 3 &#8211; especially with the prospect of a release candidate <a href="http://weblog.rubyonrails.org/2010/6/8/rails-3-0-beta-4-now-rc-in-days">in the near future</a>.    So, I spent some time playing with the new framework, and I feel like I&#8217;ve fallen in love all over again.  The goal of this post is to showcase some of the awesome new features in Rails 3 while building a generic, reusable application skeleton which follows Rails best practices.</p>
<h2>1. Generating the app</h2>
<div id="_mcePaste">To start things off, create a new project (I&#8217;ll call it &#8220;sprinter&#8221;) and set up the Git repository.</div>
<pre>&gt; rails new sprinter --database=mysql</pre>
<pre>&gt; cd sprinter/</pre>
<pre>&gt; rm public/index.html</pre>
<pre>&gt; rm public/images/rails.png</pre>
<pre>&gt; git init</pre>
<pre>&gt; git add .</pre>
<pre>&gt; git commit -m "Initial creation of the Sprinter app"</pre>
<pre>&gt; mate .</pre>
<p>As you can see, I didn&#8217;t even think about a .gitignore file.  Since the Rails community has fully embraced git as the source control system of choice, Rails 3 provides a default .gitignore file for you.</p>
<p><em>Side note: if you haven&#8217;t gotten up to speed on using git yet, you should.  GitHub has a <a title="Git Crash Course" href="http://gitref.org/">nice crash course</a>.</em></p>
<h2>2. Configuring the app</h2>
<p>The first place to start is the Gemfile.  This is the new place to declare all your gem dependencies (it used to be in &#8220;config/environment.rb&#8221;, which, by the way,  is now &#8220;config/application.rb&#8221;).    Once you open it up, you&#8217;ll see it&#8217;s pretty much the same as how you declared gems in environment.rb, except you wont be typing &#8220;config&#8221; over and over.</p>
<p>Here&#8217;s the Gemfile I use for this project:</p>
<pre>source 'http://rubygems.org'</pre>
<pre>gem 'rails', '3.0.0.beta4'</pre>
<pre>gem 'mysql'</pre>
<pre>gem 'mongrel'</pre>
<pre>group :test do</pre>
<pre>  gem "shoulda"</pre>
<pre>end</pre>
<p>Normally, I would include a few more gems here (specifically: HAML, friendly_id, authlogic, and paperclip), but this is just a quick starter app, so I omitted them for now.  I included &#8220;shoulda&#8221; in the test group simply to illustrate how to include gems purely for a test environment.  Plus, you should be using shoulda.</p>
<h2>3. Bundler</h2>
<p>Now that the gems are defined, I can use Rails 3&#8217;s new bundler to make sure all required gems are installed.  This is how you can guarantee every system is using the right gems for the project.  It&#8217;s similar to requiring gems in environment.rb, but bundler allows you to package the gems in the deliverable.  Also, bundler is far smarter than the previous system.  Previously, gem dependencies were read linearly out of config/environment.rb which had the propensity to cause issues.</p>
<p>For example, consider the following scenario.</p>
<div>
<ul>
<li>You have versions 1.2.3 and 1.2.4 of a gem (let&#8217;s call it &#8220;some-gem&#8221;) installed on your system.</li>
<li>Your app depends on &#8220;some-gem&#8221; version &#8220;&gt;= 1.2.3&#8243;, which is declared in config/environment.rb</li>
<li>A different gem required by your app depends upon &#8220;some-gem&#8221; version &#8220;= 1.2.3&#8243; </li>
</ul>
</div>
<p>Since you have version &#8220;1.2.4&#8243; installed, the &#8220;&gt;= 1.2.3&#8243; requirement would use the version &#8220;1.2.4&#8243; installed on your system (because it is the latest, greatest version).  However, when it later reads that version &#8220;= 1.2.3&#8243; is required, it fails since it already loaded version &#8220;1.2.4&#8243;.   It&#8217;s an edge case, but Bundler will prevent this from happening.</p>
<p>Anyway, I got a bit off subject there.  The next step is to use bundler to make sure all those gems are installed.</p>
<pre>&gt; sudo bundle install</pre>
<p>You&#8217;ll see it fetch the correct versions of all the gems defined in the Gemfile.</p>
<h2>4. Using jQuery</h2>
<p>One of the best features of Rails 3 is that all the javascript is unobtrusive, thus being fairly framework-agnostic.  Since I&#8217;m a big fan of jQuery, and less so of Prototype, let&#8217;s swap in jQuery by doing the following:</p>
<div>
<ol>
<li>Delete all .js files (except for &#8220;application.js&#8221;) in the &#8220;public/javascripts&#8221; directory.</li>
<li>Grab the &#8220;rails.js&#8221; file from the src directory of <a href="http://github.com/rails/jquery-ujs">http://github.com/rails/jquery-ujs</a> and place this in the &#8220;public/javascripts&#8221; directory.</li>
</ol>
</div>
<p>Believe it or not, you now have everything you need to use jQuery.  To make things more seamless though, you should create file &#8220;config/initializers/jquery.rb&#8221;, and paste the following inside:</p>
<pre>module ActionView::Helpers::AssetTagHelper

  remove_const :JAVASCRIPT_DEFAULT_SOURCES

  JAVASCRIPT_DEFAULT_SOURCES = %w(

    http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js 

    rails.js

  )

  reset_javascript_include_default

end
</pre>
<p>This will include the Google CDN hosted jQuery (saving you some bandwidth and speeding up your pages) when you use the &#8220;:defaults&#8221; javascript include tag.</p>
<p><em>Side note: Because all the javascript is unobtrusive,  some of those fun helpers like &#8220;link_to_function&#8221; no longer exist.  However, &#8220;link_to_remote&#8221; still exists, but you call it as a regular &#8220;link_to&#8221; with &#8220;:remote =&gt; true&#8221; as an option.</em></p>
<p>It&#8217;s one thing for the framework to try and enforce unobtrusive javascript, but we should also set up our code to enforce it as well.    At this point, I usually create the following helper methods in &#8220;app/helpers/application_helper.rb&#8221;:</p>
<pre>
<div>def stylesheet(*args)</div>
<div>  content_for(:stylesheets) { stylesheet_link_tag(*args) }</div>
<div>end</div>
<div>def javascript(*args)</div>
<div>  content_for(:javascripts) { javascript_include_tag(*args) }</div>
<div>end</div>
</pre>
<p>These functions help me group all the stylesheet and javascript includes together.  With that, I then update the application layout file like so:</p>
<pre>&lt;!DOCTYPE html&gt;</pre>
<pre>&lt;html&gt;</pre>
<pre>&lt;head&gt;</pre>
<pre>  &lt;title&gt;Sprinter&lt;/title&gt;</pre>
<pre>  &lt;% stylesheet :all %&gt;</pre>
<pre>  &lt;% javascript :defaults %&gt;</pre>
<pre>  &lt;%= yield(:stylesheets) %&gt;</pre>
<pre>  &lt;%= csrf_meta_tag %&gt;</pre>
<pre>&lt;/head&gt;</pre>
<pre>&lt;body&gt;</pre>
<pre>  &lt;%= yield %&gt;</pre>
<pre>  &lt;%= yield(:javascripts) %&gt;</pre>
<pre>&lt;/body&gt;</pre>
<pre>&lt;/html&gt;</pre>
<p><em>Another side note:  Rails 3 spits out pure HTML5.</em></p>
<p>Moving the javascript include tags to the bottom does several things:</p>
<div>
<ol>
<li>Any inline-javascript that depends on jQuery or any of our other methods will cause an error.  This forces you to use an external file for it (like you should).</li>
<li>There is no browser blocking when loading the javascript files, thus causing the page to load faster.</li>
</ol>
</div>
<h2>5. Rails 3 Routes</h2>
<p>Now that all the required gems are installed, we&#8217;re ready to roll.  I like to start by creating a simple &#8220;Welcome&#8221; controller for the app.  One thing to note is that all the Rails 2 &#8220;script/&#8221; commands are now part of the &#8220;rails&#8221; command.</p>
<pre>&gt; rails generate controller Welcome index</pre>
<p>Followed by an update to the &#8220;config/routes.rb&#8221; file to set the &#8220;welcome&#8221; controller as the root of the project.</p>
<pre>root :to =&gt; "welcome#index"</pre>
<p>In Rails 2, you would have declared the same thing with something like:</p>
<pre>map.root :controller =&gt; 'welcome', :action =&gt; 'index'</pre>
<p>Rails 3 routes are built to be  more extendable and require a lot less typing (notice the &#8220;controller#action&#8221; naming convention).  Let&#8217;s make sure everything&#8217;s working:</p>
<pre>&gt; rake db:create</pre>
<pre>&gt; rails server</pre>
<p>The site should now be visible at &#8220;http://localhost:3000&#8243;.  When you&#8217;re satisfied, stop the server with Ctrl+C.</p>
<h2>6. Scaffolding</h2>
<p>So far, I think this is a great starting point for quickly getting up and running on a new Rails 3 project.  However,it really doesn&#8217;t do anything yet.    So, let&#8217;s make it into a simple blog.</p>
<pre>&gt; rails generate scaffold Post title:string body:text published:boolean</pre>
<p>This looks pretty standard, but a few key things have changed for Rails 3.  One, the scaffold generates a &#8220;_form.html.erb&#8221; partial instead of repeating the form in the &#8220;new&#8221; and &#8220;edit&#8221; views, making things much DRYer.</p>
<p>This also sets up the routes like so:</p>
<pre>resources :posts</pre>
<p>Just to close the discussion on routes, consider if posts belonged to a user and also featured a &#8220;comment&#8221; action.  We could set the routes up like so:</p>
<pre>resources :users do</pre>
<pre>  resources :posts do</pre>
<pre>    member do</pre>
<pre>      get :comment</pre>
<pre>    end</pre>
<pre>  end</pre>
<pre>end</pre>
<p>Pretty clean, isn&#8217;t it?</p>
<p>Anyway, back to the app.  Let&#8217;s see how things are working.  Run:</p>
<pre>&gt; rake db:migrate</pre>
<p>Starting the server and checking out &#8220;/posts&#8221; gives you the standard Rails scaffolding page.  All is good here.</p>
<h2>7. And finally, Arel</h2>
<p>Now I can introduce my favorite part of Rails 3: Arel.</p>
<p>In a nutshell, Arel is an ORM-agnostic framework based on Relational Algebra (what the SQL language is based on).  I&#8217;m sure I&#8217;ll be blogging about it in far more detail shortly, but it essentially allows you to make all your Rails queries chainable (much like &#8220;named_scope&#8221; in Rails 2 &#8211; in fact, it was written by the same guy).</p>
<p>Open up app/controllers/posts_controller.rb and we&#8217;ll give it a shot.</p>
<p>In the &#8220;index&#8221; action, you can see that it grabs the blog posts in the standard Rails way:</p>
<pre>@posts = Post.all</pre>
<p>Normally, to only show the latest 25 published posts, we&#8217;d change this to be:</p>
<pre>@posts = Post.all(:conditions =&gt; { :published =&gt; true }, :limit =&gt; 25, : order =&gt; "posts.created_at DESC")</pre>
<p>With Arel, we can make this awesome by writing it as:</p>
<pre>@posts = Post.where(:published =&gt; true).order("posts.created_at DESC").limit(25)</pre>
<p>You should notice that, apart from a new naming convention, there is one major difference:  in Rails 3, we don&#8217;t call &#8220;.all&#8221;.  This is by choice.  We <em>could</em> call .all on that line and everything would work as expected (and in some cases, you want to call it).  However, calling &#8220;.all&#8221; forces the query to be run immediately.  But, thanks to Arel, if we leave it off, <strong>the query is only run when we actually use the data.</strong></p>
<p>So, our query is only run when the view hits:</p>
<pre>&lt;% @posts.each do |post| %&gt;</pre>
<pre>...</pre>
<pre>&lt;% end %&gt;</pre>
<p>I don&#8217;t know about you, but I think that&#8217;s awesome.  It&#8217;s cleaner, and <em>far</em> more extendable.  For example, say we wanted to have a toggle switch for published and unpublished posts.  Our &#8220;index&#8221; action could be something like:</p>
<pre>@posts = Post.order("posts.created_at DESC").limit(25)</pre>
<pre>if(params[:draft])  </pre>
<pre>  @posts = @posts.where(:published =&gt; false)</pre>
<pre>else  </pre>
<pre>  @posts = @posts.where(:published =&gt; true)</pre>
<pre>end</pre>
<p>Gorgeous, isn&#8217;t it?</p>
<p>Well, that&#8217;s it for now.  I hope this post helps you hit the ground running with Rails 3.  I&#8217;ll be sure to post more about Rails 3 as I discover it, but so far, I&#8217;m extremely excited about it.  I hope you feel the same way.  Leave your thoughts/gripes in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2010/07/20/sprinting-with-rails-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Grails &#8211; Exporting / Importing Domain Objects using DefaultGrailsDomainClass</title>
		<link>http://www.cantinaconsulting.com/2010/07/15/grails-exporting-importing-domain-objects-using-defaultgrailsdomainclass/</link>
		<comments>http://www.cantinaconsulting.com/2010/07/15/grails-exporting-importing-domain-objects-using-defaultgrailsdomainclass/#comments</comments>
		<pubDate>Thu, 15 Jul 2010 18:48:38 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[Groovy on Grails]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=422</guid>
		<description><![CDATA[Lately I&#8217;ve been working on a multi-tenant web app that contains a good-size number of domain objects. Within these objects, there exists a sub-set belonging to a root object, and the need arose to be able to quickly duplicate / populate the data within these objects between different instances of the app. It has become [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I&#8217;ve been working on a multi-tenant web app that contains a good-size number of domain objects. Within these objects, there exists a sub-set belonging to a root object, and the need arose to be able to quickly duplicate / populate the data within these objects between different instances of the app. It has become quite an interesting problem: certainly one could create some SQL scripts to export/import data, but how does one do it in a user-friendly, Groovy/Grails manner?</p>
<p id="_mcePaste">The key turned out to be the discovery of the <a title="DefaultGrailsDomainClass" href="http://www.grails.org/doc/1.3.x/api/org/codehaus/groovy/grails/commons/DefaultGrailsDomainClass.html" target="_blank">DefaultGrailsDomainClass</a> . This class performs a series of introspections on your domain objects, and allows you to programmatically access quite a bit of information on them. For example, suppose we had the following domain object:</p>
<div>
<pre style="padding-left: 30px;">class Pizza{</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 60px;">String name

BigDecimal diameter

List toppings

hasMany = [toppings:Topping]</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 30px;">}</pre>
</div>
<p id="_mcePaste">Class &#8216;Pizza&#8217; contains a name / description, diameter, and a many-to-many relationship with the &#8216;Topping&#8217; class (although not defined here). Nice and simple&#8230; now, the good stuff.</p>
<p id="_mcePaste">By passing a Domain Object class to DefaultGrailsDomainClass, we can access a good deal of info about that Domain Object. Among other things there are methods to access a Map of the constraints, determine whether or not a property is a relation (1:1,1:m,m:m), and access the properties directly by obtaining a set of <a title="GrailsDomainClassProperties" href="http://grails.org/doc/1.3.x/api/org/codehaus/groovy/grails/commons/GrailsDomainClassProperty.html" target="_blank">GrailsDomainClassProperties</a> . Of particular use to me is the DefaultGrailsDomainClass.getPersistantProperties() method, which returns a GrailsDomainClassProperty List of all the properties that are persisted to the database. That&#8217;s pretty excellent.</p>
<p id="_mcePaste">To illustrate this, let&#8217;s get the persistent properties for a Pizza:</p>
<address id="_mcePaste" style="padding-left: 30px;"><span style="color: #333333;">def pizzaProperties = new DefaultGrailsDomainClass(Pizza.class).getPersistantProperties()</span></address>
<address style="padding-left: 30px;"><span style="color: #333333;"><br /></span></address>
<p id="_mcePaste">pizzaProperties now contains a list of &#8216;DefaultGrailsDomainClassProperty&#8217; objects. If we iterate through them, we can see the following information:</p>
<address>
<p><span style="color: #333333;">[name=diameter,type=double,persistent=true, optional=false, association=false, bidirectional=false, association-type=&lt;null&gt;]</span></p>
<p><span style="color: #333333;">[name=name,type=class java.lang.String,persistent=true, optional=false, association=false, bidirectional=false, association-type=&lt;null&gt;]</span></p>
<p><span style="color: #333333;">[name=toppings,type=interface java.util.List, persistent=true, optional=true, association=true, bidirectional=false, association-type=one-to-many]</span></p>
<p> </p>
<p> </p>
</address>
<p id="_mcePaste">Think of the possibilities of what can be accomplished by programmatically accessing the properties on your domain object! However, I am not exceedingly clever:</p>
<div>
<address style="padding-left: 30px;">def exportClassSingle(ConfigObject co, String className, objInstance){</address>
</div>
<div id="_mcePaste">
<address style="padding-left: 60px;">if(objInstance){</address>
</div>
<div id="_mcePaste">
<address style="padding-left: 60px;">/*</address>
</div>
<div id="_mcePaste">
<address style="padding-left: 90px;">The DefaultGrailsDomainClass allows discovery of the persistent properties for a domain object.</address>
</div>
<div id="_mcePaste">
<address style="padding-left: 60px;">*/</address>
</div>
<div id="_mcePaste">
<address style="padding-left: 60px;">def props = new DefaultGrailsDomainClass(objInstance.class).getPersistantProperties()</address>
</div>
<div id="_mcePaste">
<address style="padding-left: 60px;">/*</address>
</div>
<div id="_mcePaste">
<address style="padding-left: 90px;">getPersistantProperties generates a list of &#8220;DefaultGrailsDomainClassProperty&#8221; which contains a
<p>good deal of info about each property.</p>
<p> </p>
</p></address>
</div>
<div id="_mcePaste">
<address style="padding-left: 60px;">*/</address>
</div>
<div id="_mcePaste">
<address style="padding-left: 60px;">for(p in props){</address>
</div>
<div id="_mcePaste">
<address style="padding-left: 90px;">if(!p.isAssociation()){</address>
</div>
<div id="_mcePaste">
<address style="padding-left: 120px;">co[className][p.name] = preExportClean(objInstance[p.name])</address>
</div>
<div id="_mcePaste">
<address style="padding-left: 90px;">}</address>
</div>
<pre id="_mcePaste">
<address style="padding-left: 90px;">else{//do something clever!}

}</address>
</pre>
<pre id="_mcePaste">
<address style="padding-left: 30px;">}</address>
</pre>
<p id="_mcePaste">The exportClassSingle method above accepts the ConfigObject which will be populated with the domain object&#8217;s data, the name of the class, and an instance of the domain object. It is relatively simple: it takes the class, loads its persistent properties, loops through through them and if the property is not an association, it is added to the config object.  By repeatedly calling the method for each of our Domain objects, we build up the ConfigObject which contains class and instance data. The preExportClean() method looks for and escapes any usage of &#8216;$&#8217;, which can cause some odd behavior if not escaped. We ignore associations here because in the real app, everything is connected to one root object; if there were associations among the child objects that we wished to capture then the above method would be quite different.</p>
<div>
<p>The resulting ConfigObject can then be converted into a String containing a DSL describing your objects and data. The string can then be loaded back into a ConfigObject using the ConfigSlurper.</p>
</div>
<p id="_mcePaste">Given the following DSL:</p>
<div id="_mcePaste">
<pre style="padding-left: 30px;">pizza{</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 60px;">pizza_0{</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 90px;">name="Small"</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 90px;">diameter="8.0"</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 60px;">}</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 60px;">pizza_1{</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 90px;">name="Medium"</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 90px;">diameter="14.5"</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 60px;">}</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 60px;">pizza_2{</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 90px;">name="Large"</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 90px;">diameter="21.0"</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 60px;">}</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 30px;">}</pre>
</div>
<p id="_mcePaste">and assuming it&#8217;s saved in a String called &#8216;pizzaDSL&#8217;, we can import this data into our system using the following steps:</p>
<div id="_mcePaste">
<p>1. Import the DSL using ConfigSlurper.</p>
</div>
<pre style="padding-left: 30px;">ConfigObject config = new ConfigSlurper().parse( pizzaDSL )</pre>
<p id="_mcePaste">The ConfigObject config now contains a map of ConfigObjects. Using the key of &#8216;pizza&#8217; returns a map of 3 more ConfigObjects.</p>
<p>2. Construct objects using the configObject.</p>
<div id="_mcePaste">
<pre style="padding-left: 30px;">config["pizza"].each{key,map-&gt;</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 60px;">Pizza p = new Pizza()</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 60px;">p.properties = map</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 60px;">//set toppings</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 60px;">p.save()</pre>
</div>
<div id="_mcePaste">
<pre style="padding-left: 30px;">}</pre>
</div>
<div id="_mcePaste">
<p>One could also iterate through the root config object (in the case where we had more objects, e.g. &#8216;topping&#8217;) and use the key to determine which object to create and populate. This simple case has only one class, Pizza (and thus only one key).</p>
</div>
<p id="_mcePaste">3. Celebrate</p>
<p id="_mcePaste">Well, that&#8217;s it. I hope this helps explain the usage of the Default Domain Class and that you all find a usage for it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2010/07/15/grails-exporting-importing-domain-objects-using-defaultgrailsdomainclass/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Googlebook?</title>
		<link>http://www.cantinaconsulting.com/2010/07/13/googlebook/</link>
		<comments>http://www.cantinaconsulting.com/2010/07/13/googlebook/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 20:08:55 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Social]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[google me]]></category>
		<category><![CDATA[social networking]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=397</guid>
		<description><![CDATA[Friendster&#8230; MySpace&#8230; Facebook?
In what could be one of this summer&#8217;s only worthy entertainment highlights (Inception aside), it looks as if Boss Google may be ordering up a hit on the family Zuckerberg. Under the working title &#8220;Google Me&#8221; (ala &#8220;Analyze This&#8221;), the story also features Facebook&#8217;s agrarian darling Zynga, who has left the family farm [...]]]></description>
			<content:encoded><![CDATA[<p>Friendster&#8230; MySpace&#8230; Facebook?</p>
<p>In what could be one of this summer&#8217;s only worthy entertainment highlights (<a href="http://trailers.apple.com/trailers/wb/inception/" target="new">Inception</a> aside), it looks as if Boss Google may be ordering up a hit on the family Zuckerberg. Under the working title &#8220;Google Me&#8221; (ala &#8220;Analyze This&#8221;), the story also features Facebook&#8217;s agrarian darling Zynga, <a href="hhttp://techcrunch.com/2010/07/10/google-secretly-invested-100-million-in-zynga-preparing-to-launch-google-games/" target="new">who has left the family farm</a> for Google&#8217;s greener pastures. The search goliath seems to be launching another salvo (Orkut? Wave? Buzz?) on the social space. But will anyone watch?</p>
<p>Wait a minute &#8211; what about SNF? Only yesterday the headlines, the talk shows, and the naysayers were all passing the can around to raise awareness for that digital menace, <a href="http://www.zdnet.com/blog/social/could-2007-be-the-year-of-social-network-fatigue/53" target="new">Social Networking Fatigue</a>. Apparently that&#8217;s all behind us now: &#8220;<a href="http://mashable.com/2010/07/09/gen-y-social-networking/" target="new">You can pry my user profile from my cold, dead hands</a>,&#8221; says Gen Y. According to young lasses everywhere, &#8220;<a href="http://mashable.com/2010/07/07/oxygen-facebook-study/" target="new">I&#8217;ll take mine before coffee thank you</a>.&#8221;</p>
<p>The obvious questions beg, are folks willing to set up yet another profile on yet another social networking site? Or do the gazillions of existing Gmail accounts make the medicine go down? Google&#8217;s ubiquitous in-roads into all tasks digital certainly may help tip the scales. On the other hand, who doesn&#8217;t have a Facebook profile (beyond that &#8220;<a href="http://en.wikipedia.org/wiki/Elmer_Fudd" target="new">whaskely</a>&#8220; <a href="http://www.theregister.co.uk/2010/06/01/quit_facebook_day/" target="new">gang of 35,000</a>)? Naturally the open sorcerers and early adopters are sure to line up and spread the Holy Google Invite, and perhaps that&#8217;ll be enough to get the momentum going. Then again, Wave anyone?</p>
<p>Interestingly, at the same time the rumors swirl about Googlebook, Microsoft announces <a href="http://mashable.com/2010/07/13/outlook-facebook/" target="new">Facebook integration into it&#8217;s Outlook mothership</a>. But can a plug-in really even those odds? Will Outlookers actively seek out and install an email client plug-in?</p>
<p>And still the plot thickens! We learned today that a New York man has teamed up with Johnny Law to <a href="http://www.dailytech.com/Man+Claims+to+Own+84+of+Facebook/article19025.htm" target="new">claim his piece</a> of the Zuckerberg empire. Could he be a Google mole?</p>
<p>Stay tuned. In the meantime, grab your popcorn bins and head over to see the only film that promises to be <a href="http://www.totalfilm.com/features/27-most-boring-movies/the-black-dahlia-2006#content" target="new">more boring than &#8220;The Black Dahlia&#8221;</a>, <a href="http://trailers.apple.com/trailers/sony_pictures/thesocialnetwork/" target="new">&#8220;The Social Network&#8221;</a> (perhaps the bigger question is how can this possibly be from the <a href="http://www.imdb.com/name/nm0000399/" target="new">same director</a> as &#8220;Fight Club&#8221;?) </p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2010/07/13/googlebook/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thoughts from Streaming Media East</title>
		<link>http://www.cantinaconsulting.com/2010/06/01/thoughts-from-streaming-media-east/</link>
		<comments>http://www.cantinaconsulting.com/2010/06/01/thoughts-from-streaming-media-east/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 15:54:45 +0000</pubDate>
		<dc:creator>alec</dc:creator>
				<category><![CDATA[HTML5]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[measurement]]></category>
		<category><![CDATA[online video]]></category>
		<category><![CDATA[streaming media]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=386</guid>
		<description><![CDATA[Recently, some colleagues and I attended the Streaming Media East conference in NYC. I found the conference fascinating, not so much for the content of the individual sessions, but for the main themes that bubbled to the surface over two days of exhibits and breakout discussions.
We&#8217;ve been here before. Online video gets portrayed as a [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, some colleagues and I attended the Streaming Media East conference in NYC. I found the conference fascinating, not so much for the content of the individual sessions, but for the main themes that bubbled to the surface over two days of exhibits and breakout discussions.</p>
<p><strong>We&#8217;ve been here before</strong>. Online video gets portrayed as a new environment with new rules and new things to consider and sure, there&#8217;s some different dimensions to creating and deploying video as opposed to straight text/images, but at the end of the day, it&#8217;s still content. It&#8217;s new and still very much in that me-too stage, but companies are going to have to figure out how it serves their business or they&#8217;ll stop doing it. Not much different than the web for that matter. And similar rules apply to creating an online video strategy that would apply to creating a web site strategy, or any other business strategy. Understand your audience and their needs, match those needs to your business objectives and create compelling media and features that meet those needs and objectives. Oh, and don&#8217;t forget to create goals and how you&#8217;re going to measure them. Which brings me to the next point.</p>
<p><strong>Measuring video is hard</strong>. Actually, measuring video use is easy at a basic level. What&#8217;s hard is measuring how your video is being used outside of your &#8220;control&#8221; and what&#8217;s even harder is figuring out whether your video is actually serving the business need you had in mind. No one has the silver bullet for this one but I think it&#8217;s a combination of planning (per my previous point) and doing the hard work to integrate your video statistics into your overall web measurement approach. Out of the box the video stats from OVPs are islands unto themselves, building those bridges will pay off in the long run.</p>
<p><strong>HTML is back in vogue</strong>. The most popular session I attended was hands down the discussion on HTML5 and video. The discussion itself wasn&#8217;t particularly enlightening, but it is apparent from the interest of that audience combined with the buzz all over the internet (thanks Apple and Adobe!) has elevated this topic to near cult status. Once we parse through the hype, however, HTML5 does have the makings for a quantum shift in the development and deployment of media assets on the Web. The ability to replicate much of the interactive functionality inherent in frameworks such as Flash in a simpler, more open format such as HTML will have ramifications for years to come &#8211; and not just for Adobe. We&#8217;re going to dive into this topic in much more detail in coming posts &#8211; it&#8217;s too important to just riff on in a simple blog post such as this one.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2010/06/01/thoughts-from-streaming-media-east/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gory Details of In-App Purchases</title>
		<link>http://www.cantinaconsulting.com/2010/05/14/gory-details-of-in-app-purchases/</link>
		<comments>http://www.cantinaconsulting.com/2010/05/14/gory-details-of-in-app-purchases/#comments</comments>
		<pubDate>Fri, 14 May 2010 18:25:18 +0000</pubDate>
		<dc:creator>glenn</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=381</guid>
		<description><![CDATA[Chris Adamson has posted a great summary of his presentation from the Voices That Matter: iPhone Developers Conference where he dives into the possibilities and perils of implementing in-app purchases in your iPhone applications.  These follow up nicely on his original post on the topic (An In-App Purchase Brain Dump).
These posts are the best posts [...]]]></description>
			<content:encoded><![CDATA[<p>Chris Adamson has posted <a href="http://www.subfurther.com/blog/?p=1026">a great summary</a> of his presentation from the <a href="http://www.voicesthatmatter.com/iphone2010/">Voices That Matter: iPhone Developers Conference</a> where he dives into the possibilities and perils of implementing in-app purchases in your iPhone applications.  These follow up nicely on his original post on the topic (<a href="http://www.subfurther.com/blog/?p=856">An In-App Purchase Brain Dump</a>).</p>
<p>These posts are the best posts I&#8217;ve seen yet on the subject, with real, nitty-gritty details about implementing I-AP.</p>
<p>Executive summary: 1 FTE for 1 month to convert an existing, fully operational app to one enabled for in-app purchases.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2010/05/14/gory-details-of-in-app-purchases/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creation and Collaboration on the iPhone</title>
		<link>http://www.cantinaconsulting.com/2010/05/13/creation-and-collaboration-on-the-iphone/</link>
		<comments>http://www.cantinaconsulting.com/2010/05/13/creation-and-collaboration-on-the-iphone/#comments</comments>
		<pubDate>Thu, 13 May 2010 16:23:03 +0000</pubDate>
		<dc:creator>glenn</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=357</guid>
		<description><![CDATA[Much of the media buzz about iPhone OS 4.0 has focused on multitasking, home screen customizations and iAds.  While these changes are significant, at Cantina we&#8217;ve been wondering what other new features might emerge in 4.0 (and beyond) &#8211; and what new classes of applications they might enable.
While the full list of iPhone OS 4.0 [...]]]></description>
			<content:encoded><![CDATA[<p>Much of the media buzz about iPhone OS 4.0 has focused on <a href="http://gizmodo.com/5512656/how-multitasking-works-in-the-new-iphone-os-40">multitasking</a>, <a href="http://www.ilounge.com/index.php/news/comments/iphone-os-4.0-multitasking-folders-home-screen-ibooks-rich-ads/">home screen customizations</a> and <a href="http://mashable.com/2010/04/08/apple-iads/">iAds</a>.  While these changes are significant, at Cantina we&#8217;ve been wondering what other new features might emerge in 4.0 (and beyond) &#8211; and what new classes of applications they might enable.</p>
<p>While the full list of iPhone OS 4.0 features is yet to be publicly disclosed, there are a number of iPad OS features (referred to by Apple as &#8220;iPhone OS 3.2&#8243;) that could conceivably show up on our iPhones in the future.  Some examples:</p>
<ul>
<li>The ability to email an app-specific file to a friend, and have them open it up on their own device in the proper app (<a href="http://developer.apple.com/iphone/library/releasenotes/General/WhatsNewIniPhoneOS/Articles/iPhoneOS3_2.html#//apple_ref/doc/uid/TP40009337-SW8">Document Support</a>)</li>
<li>The ability for an app to generate a PDF with text and images (<a href="http://developer.apple.com/iphone/library/releasenotes/General/WhatsNewIniPhoneOS/Articles/iPhoneOS3_2.html#//apple_ref/doc/uid/TP40009337-SW2">PDF Generation</a>)</li>
<li>The ability to easily move app-specific files back and forth from  your mobile device to your laptop (<a href="http://developer.apple.com/iphone/library/releasenotes/General/WhatsNewIniPhoneOS/Articles/iPhoneOS3_2.html#//apple_ref/doc/uid/TP40009337-SW11">File  Sharing Support</a>)</li>
</ul>
<p>None of these features is earth-shattering in its own right; certainly it would be possible to accomplish any or all of these behaviors today by using the iPhone app as a &#8220;thin client&#8221;, and pushing the hard work like generating PDFs, sharing documents, and managing files up to a web app server.</p>
<p>What is significant about having these capabilities on the device itself is how much easier it will be for developers to build apps that enable these behaviors, and for consumers to adopt them:</p>
<ul>
<li>App Developers won&#8217;t have to lease a server and pay bandwidth fees to enable these types of apps</li>
<li>App Developers won&#8217;t have to leave the comfort of their chosen programming language and tools (XCode / Cocoa)</li>
<li>Consumers will be able to leverage familiar collaboration and file management paradigms like email, attachments, and copying files to and from the desktop</li>
</ul>
<p>Most apps today are focused around <strong>consumption</strong> &#8211; consuming content, data or interactive entertainment for a short period of time, and then closing the app.  Features like those above could enable <strong>creation</strong> and <strong>collaboration</strong> behaviors &#8211; where the activity spent in the app yields some tangible artifact, which can be exported, transformed, or shared with other app users.</p>
<p>The possibilities exposed for consumer apps are intriguing, but the biggest impact may be felt in the enterprise arena &#8211; where creation and collaboration are more fundamental to day-to-day operations.  This is a point that others have pondered with the iPad, where the large touchscreen presumably makes it a better fit for content creation.</p>
<p>Definitely will be an interesting area to watch.  Please comment if you&#8217;ve heard of particularly clever mobile collaboration apps in the enterprise.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2010/05/13/creation-and-collaboration-on-the-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Calling all Technical Architects and Project/Program Managers!</title>
		<link>http://www.cantinaconsulting.com/2010/01/08/calling-all-technical-architects-and-projectprogram-managers/</link>
		<comments>http://www.cantinaconsulting.com/2010/01/08/calling-all-technical-architects-and-projectprogram-managers/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 21:48:30 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=312</guid>
		<description><![CDATA[Cantina is actively looking for senior level Technical Architects and Project/Program Managers with technical consulting experience. Please have anyone that is interested from your networks send us a resume at jobs@cantinaconsulting.com. Candidates should based in the greater Boston area. Thank you!
]]></description>
			<content:encoded><![CDATA[<p>Cantina is actively looking for senior level Technical Architects and Project/Program Managers with technical consulting experience. Please have anyone that is interested from your networks send us a resume at jobs@cantinaconsulting.com. Candidates should based in the greater Boston area. Thank you!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2010/01/08/calling-all-technical-architects-and-projectprogram-managers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Analytics Event Tracking now available to all accounts</title>
		<link>http://www.cantinaconsulting.com/2009/07/22/google-analytics-event-tracking-now-available-to-all-accounts/</link>
		<comments>http://www.cantinaconsulting.com/2009/07/22/google-analytics-event-tracking-now-available-to-all-accounts/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 17:33:55 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[RIA / Flash]]></category>
		<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=207</guid>
		<description><![CDATA[We tend to do a fair bit of analytics integrations for our clients, mainly in Google Analytics and Omniture.  Both provide great features for tracking standard web site usage metrics, including page views, visits, entry/exit points, and more.  Until recently, Omniture has had a leg up in one particular area of the analytics [...]]]></description>
			<content:encoded><![CDATA[<p>We tend to do a fair bit of analytics integrations for our clients, mainly in Google Analytics and Omniture.  Both provide great features for tracking standard web site usage metrics, including page views, visits, entry/exit points, and more.  Until recently, Omniture has had a leg up in one particular area of the analytics space, namely <strong>video metrics</strong>.</p>
<p>It is beyond value what a content publisher, advertiser, syndicator or whoever else you can think of can glean from metrics that track the behavior of viewers of video content.  Here are some key items that can be &#8220;gleaned&#8221;:</p>
<ul>
<li>Popularity of certain videos</li>
<li>Which kinds of video content retains users (e.g., short form vs. long form, ad-supported vs. free, etc)</li>
<li>Abandonment of playback (e.g., when does a user call it quits on a clip)</li>
<li>How is the content shared?  Does a user send it to a friend, to Facebook, to a blog?</li>
</ul>
<p> </p>
<p>This kind of data can clearly help a variety of video content providers and advertisers target content better to their users and produce better content overall.  In this space, Omniture has been leading the charge for a <a href="http://newteevee.com/2008/03/05/omniture-enhances-tracking-lets-marketers-analyze-video-use/">while now</a> with their <a href="http://www.omniture.com/en/products/online_analytics/sitecatalyst">SiteCatalyst</a> product suite, which includes specific video metrics.  The product suite includes an API which can integrate directly into a Flash-based video player, with particularly close integration with <a href="http://www.brightcove.com/en/products/analytics/analytics-integrations">Brightcove&#8217;s video players</a>, and provides hooks to track the various user behaviors that can occur during video playback.</p>
<p>Google does not want to be left behind in this space, given that they wish to &#8220;organize the world&#8217;s information&#8221;, and have recently opened up a relatively new component of their <a href="http://www.google.com/analytics/">Google Analytics</a> to all users of that service.  The <a href="http://analytics.blogspot.com/2009/06/event-tracking-now-available-in-all.html">Event Tracking API has now been added to all Google Analytics accounts</a>, whereas previously it was an invite-only beta feature.  This portion of their analytics API allows you to track almost arbitrary event-oriented data, without affecting the more conventional web site-oriented metrics, such as pageviews.  Event Tracking really enables users of Google Analytics to leverage the platform for video tracking, allow you to define and measure user events that are important to your video content and players.  Here are some examples:</p>
<ul>
<li>Start playback of video</li>
<li>Pauses and resumes</li>
<li>Skipping backwards or forwards in a clip</li>
<li>Turning the volume up or down</li>
<li>How far the user got before stopping or moving to another clip</li>
</ul>
<p> </p>
<p>But the richness this kind of event tracking doesn&#8217;t stop there.  With the proliferation of RIA applications on the web, you now have the opportunity to track user behavior, beyond video playback, at a greater level of detail.</p>
<ul>
<li>Track search terms within Flash or Flex-based applications</li>
<li>Follow navigation paths through RIA applications without incurring page views in your metrics</li>
<li>Track viral features in a video player or other RIA application: blog posts &amp; social link sharing (Delicious, Digg, Reddit, StumbleUpon)</li>
<li>The list goes on&#8230;</li>
</ul>
<p> </p>
<p>Check out a great primer on using the API at the link below.</p>
<p><a href="http://www.insideria.com/2009/02/using-google-analytics-within.html">http://www.insideria.com/2009/02/using-google-analytics-within.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2009/07/22/google-analytics-event-tracking-now-available-to-all-accounts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Boston Grails Users&#8217; Group</title>
		<link>http://www.cantinaconsulting.com/2009/06/02/boston-grails-users-group/</link>
		<comments>http://www.cantinaconsulting.com/2009/06/02/boston-grails-users-group/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 19:14:26 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=181</guid>
		<description><![CDATA[As I&#8217;ve mentioned before, we here at Cantina are big fans of Groovy and Grails, and we are disappointed that the language is not used more widely. To do our part to spread joy that is Groovy, we&#8217;ve started a group on Meetup.com for Boston-based users (start local!). Check us out here: http://www.meetup.com/Grails-Boston. Our focus [...]]]></description>
			<content:encoded><![CDATA[<p>As I&#8217;ve mentioned before, we here at Cantina are big fans of Groovy and Grails, and we are disappointed that the language is not used more widely. To do our part to spread joy that is Groovy, we&#8217;ve started a group on Meetup.com for Boston-based users (start local!). Check us out here: <a title="Grails Group on Meetup" href="http://www.meetup.com/Grails-Boston" target="_blank">http://www.meetup.com/Grails-Boston</a>. Our focus will be to get together with other fans of Groovy/Grails and share ideas, present work members have done, show-off some plugins (check out <a title="Cantina Consutling Grails Plugins" href="link http://www.cantinaconsulting.com/grails-plugins/" target="_blank">ours</a>), and generally expand everyone&#8217;s knowledge of the language and framework. We&#8217;d love to have anyone who&#8217;s interested join us, even those new to Grails.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2009/06/02/boston-grails-users-group/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Real Time Web</title>
		<link>http://www.cantinaconsulting.com/2009/05/20/the-real-time-web/</link>
		<comments>http://www.cantinaconsulting.com/2009/05/20/the-real-time-web/#comments</comments>
		<pubDate>Wed, 20 May 2009 14:06:06 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[real-time]]></category>
		<category><![CDATA[Techcrunch]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=165</guid>
		<description><![CDATA[The changing dynamics of the web has been something we&#8217;ve talked a lot about lately.   The shift toward real time services has impacted the way companies are thinking about the web.  Twitter is currently leading the charge in the real time information and many people think it&#8217;s going to become the real time search engine [...]]]></description>
			<content:encoded><![CDATA[<p>The changing dynamics of the web has been something we&#8217;ve talked a lot about lately.   The shift toward real time services has impacted the way companies are thinking about the web.  Twitter is currently leading the charge in the real time information and many people think it&#8217;s going to become the real time search engine of the web, ousting Google when it comes to real time information and current events.</p>
<p><a href="http://www.Techcrunch.com">Techcrunch</a> just wrote a great article on how we&#8217;re shifting away from <a href="http://www.techcrunch.com/2009/05/17/jump-into-the-stream/">pages and into streams</a>.  I think the article raises a great point that this is a huge opportunity for start-ups to really change the status quo and start developing applications that work in real time.</p>
<p>So, the question I would raise is how can your company shift it&#8217;s products toward a real time web?  Think about the big internet brands and what would happen if they had to live in the real time web.  What if companies like Amazon, Ebay, and Google had real time services?  We also know that every time our economy has gone through a shift, new companies and ideas emerge that make us re-think our perception of the web.  In other words, if you&#8217;ve got an idea for the real time web, this is your chance to go out and build it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2009/05/20/the-real-time-web/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Plugin Development in Grails</title>
		<link>http://www.cantinaconsulting.com/2009/05/19/plugin-development-in-grails/</link>
		<comments>http://www.cantinaconsulting.com/2009/05/19/plugin-development-in-grails/#comments</comments>
		<pubDate>Wed, 20 May 2009 00:22:18 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Groovy on Grails]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=159</guid>
		<description><![CDATA[We&#8217;ve had a bit of time to jump back into Grails plugin development (or maintenance as it were) and couldn&#8217;t be happier to find the recent improvements in Grails 1.1.  The biggest improvement (though perhaps not advertised as such) to me, was the inclusion of functionality that allows plugin developers to build test applications [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve had a bit of time to jump back into Grails plugin development (or maintenance as it were) and couldn&#8217;t be happier to find the recent improvements in Grails 1.1.  The biggest improvement (though perhaps not advertised as such) to me, was the inclusion of functionality that allows plugin developers to build test applications against the live, &#8220;unpacked&#8221; version of the plugin, which is to say, the Grails application that implements the plugin itself.</p>
<p>This may sound esoteric, but to someone doing plugin development in Grails, it&#8217;s a life saver, and here&#8217;s why.</p>
<p>When building a plugin for Grails, the plugin itself is built as a Grails application.  This has many benefits, including in some cases being able to run the plugin and test controllers and domain classes directly in the running plugin.  However, most, if not all plugins are intended to <em>plug into</em> another Grails application.  Given that, the only real way to test the usability of your plugin API, and whether the plugin works in the context of larger Grails application, is to install the plugin into another Grails application.  Here&#8217;s an example:</p>
<ol>
<li>I&#8217;m developing Plugins A and B to be installed in a new Grails CMS application I&#8217;m building</li>
<li>Plugin A depends on Plugin B to function</li>
<li>Once Plugin B is in good enough shape, I&#8217;ll install it into Plugin A using the Grails <em>install-plugin</em> command</li>
<li>Once Plugin A is in good enough shape, I can install it and Plugin B into my Grails CMS application</li>
<li>After testing the CMS for a while, I discover a bug in Plugin B which also requires a small change in Plugin A to accommodate the bug fix (are you still with me?)</li>
<li>I fix the bug in Plugin B and repackage</li>
<li>I remove Plugin B from Plugin A and install the latest version of Plugin B into Plugin A to make the changes required in Plugin A and repackage</li>
<li>In the CMS application, I remove both of the plugins and reinstall both Plugins into the CMS</li>
<li>I become tired of installing and uninstalling plugins and go out for beers</li>
</ol>
<p>With Grails 1.1, this development cycle is improved drastically.  Now, during development you can provide explicit locations for Grails plugin projects, without needing to install the plugin, to develop against that plugin.  Here&#8217;s an excerpt from the <a href="http://grails.org/1.1+Release+Notes">Grails 1.1 release notes</a>:</p>
<blockquote><p>An application can now load plugins from anywhere on the file system, even if they have not been installed. Simply add the location of the (unpacked) plugin to you BuildConfig.groovy file:</p>
<p><code>// Useful to test plugins you are developing.<br />
grails.plugin.location.jsecurity = "/home/dilbert/dev/plugins/grails-jsecurity"</p>
<p>// Useful for modular applications where all plugins and<br />
// applications are in the same directory.<br />
grails.plugin.location.'grails-ui' = "../grails-grails-ui"</code></p>
<p>This is particularly useful in two cases:</p>
<ol>
<li>You are developing a plugin and want to test it in a real application without packaging and installing it first.</li>
<li>You have split an application into a set of plugins and an application, all in the same &#8220;super-project&#8221; directory.
</li>
</ol>
</blockquote>
<p>Now if you want to test your plugins in the context of a larger application, you can do so without the pain of constant reinstallation.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2009/05/19/plugin-development-in-grails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web Applications &#8211; What does it take?</title>
		<link>http://www.cantinaconsulting.com/2009/05/18/web-applications-what-does-it-take/</link>
		<comments>http://www.cantinaconsulting.com/2009/05/18/web-applications-what-does-it-take/#comments</comments>
		<pubDate>Mon, 18 May 2009 18:56:18 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[startups]]></category>
		<category><![CDATA[web applications]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=150</guid>
		<description><![CDATA[One of the founders of Woofoo just wrote a terrific article on what it takes to build a web application called &#8220;Web App Autopsy&#8220;.  They were lucky enough to get some great information from three other firms, Blinksale, Feedburner and RegOnline.  I think the charts and information they put together are great, but if you [...]]]></description>
			<content:encoded><![CDATA[<p>One of the founders of Woofoo just wrote a terrific article on what it takes to build a web application called &#8220;<a href="http://particletree.com/features/web-app-autopsy/" target="_blank">Web App Autopsy</a>&#8220;.  They were lucky enough to get some great information from three other firms, <a href="http://www.blinksale.com" target="_blank">Blinksale</a>, <a href="http://www.feedburner.com" target="_blank">Feedburner</a> and <a href="http://www.regonline.com" target="_blank">RegOnline</a>.  I think the charts and information they put together are great, but if you dig into the numbers a little deeper you start to see what it really takes to build a web application.</p>
<p>From a time perspective (you have to exclude RegOnline because it was a nights a weekend project) it takes on average about 5 months to launch one of these applications and you need roughly 3 or 4 engineers to get it done.  My guess is that most of these companies boot strapped their development but current estimates say developing a web application costs anywhere from 50k to a few hundred based on complexity.  It&#8217;s also great to see these rapid development frameworks, such as Ruby on Rails, are accelerating development and time to market.</p>
<p>Lastly, I would also emphasize their focus on business processes. Many early stage companies completely neglect support needs, such as returns, customer compliants, etc.  It can end up costing you a lot of time and money if you don&#8217;t have systems on the back end to handle customer support issues.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2009/05/18/web-applications-what-does-it-take/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Putting a Stranglehold on your GUI Applications with wxPython</title>
		<link>http://www.cantinaconsulting.com/2009/05/14/wxpython_first_impressions/</link>
		<comments>http://www.cantinaconsulting.com/2009/05/14/wxpython_first_impressions/#comments</comments>
		<pubDate>Thu, 14 May 2009 22:12:32 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[wxPython]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=152</guid>
		<description><![CDATA[It&#8217;s been a few weeks now since I signed up with the group here at Cantina, and so far I&#8217;ve had a great time. I&#8217;ve had the opportunity to learn quite a bit about online video distribution &#38; technologies, expand my knowledge of Flex / Flash, play around with Amazon&#8217;s Cloud solutions, and learn the [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a few weeks now since I signed up with the group here at Cantina, and so far I&#8217;ve had a great time. I&#8217;ve had the opportunity to learn quite a bit about online video distribution &amp; technologies, expand my knowledge of Flex / Flash, play around with Amazon&#8217;s Cloud solutions, and learn the excellent framework <a title="Grails" href="http://www.grails.org/" target="_blank">Groovy on Grails</a>. If you are familiar with Rails and like Java, I suggest giving it a try. The rest of the guys here are big fans and we&#8217;re doing our part to expand the Grails community and develop some great plugins.</p>
<p>In turn, I hope to encourage the use of my current favorite language, Python (see <a href="http://www.diveintopython.org/" target="_blank">http://www.diveintopython.org/</a> for a good tutorial). For an interpreted language (it does compile to c byte code at runtime), its capabilities and community support are overwhelmingly substantial. I&#8217;m continually surprised as I discover more; its breadth is so great, that Python leaves itself open to <a title="Python - flying" href="http://xkcd.com/353/" target="_blank">satire</a> ( also: <a href="http://xkcd.com/409/" target="_blank">here</a> and <a href="http://xkcd.com/413/" target="_blank">here</a>). I could drone on,  evangelizing its advantages at some detail (and bore everyone to tears, I&#8217;m sure), but that&#8217;s not why I&#8217;m writing today. No, the point here is to give a quick presentation on a particular package I&#8217;ve just started using that amazes me, and it should get more use: <a title="wxPython.org" href="http://www.wxpython.org/" target="_blank">wxPython</a>.</p>
<p>WxPython is module for Python that is essentially a wrapper for an open source project called <a href="http://wxwidgets.org/" target="_blank">wxWidgets</a>, so most of the credit should go to them. WxWidgets is certainly widely used (link: <a href="http://wxwidgets.org/about/users.htm" target="_blank">http://wxwidgets.org/about/users.htm</a> ); it&#8217;s a package that allows developers to quickly and easily access the GUI components in Windows, OS X, and various flavors of Linux. This allows development of applications that look native to the OS. WxPython allows one to rapidly develop applications entirely in Python, that look native to the OS. Imagine writing an application in OS X, then moving the code to a Windows or Ubuntu machine and having it work and look perfectly without any modifications! No more dealing with .dlls or compiling on individual machines.. just &#8216;python &lt;appname&gt;.py&#8217;.</p>
<p>In practice, it&#8217;s surprisingly easily to generate an entire event-driven application. The basic order of implementation is (1) design layout of your buttons,menus, widgets, etc, (2) implement event handlers, (3) bind event listeners to buttons / actions. I&#8217;d post some of my code, but it&#8217;s almost all currently in an NDA&#8217;ed project, so instead here&#8217;s some sample code from <a href="http://wiki.wxpython.org/AnotherTutorial" target="_blank">http://wiki.wxpython.org/AnotherTutorial</a> that creates a program with a toolbar:<br />
<span style="color: #0000ff;"><br />
</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;">#!/usr/bin/python</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;"><br />
# toolbar.py</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;"><br />
import wx</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;"><br />
class MyToolBar(wx.Frame):</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;"> def __init__(self, parent, id, title):</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(350, 250))</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"><br />
vbox = wx.BoxSizer(wx.VERTICAL)</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER)</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> toolbar.AddSimpleTool(1, wx.Image(&#8217;stock_new.png&#8217;, wx.BITMAP_TYPE_PNG).ConvertToBitmap(), &#8216;New&#8217;, &#8221;)</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> toolbar.AddSimpleTool(2, wx.Image(&#8217;stock_open.png&#8217;, wx.BITMAP_TYPE_PNG).ConvertToBitmap(), &#8216;Open&#8217;, &#8221;)</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> toolbar.AddSimpleTool(3, wx.Image(&#8217;stock_save.png&#8217;, wx.BITMAP_TYPE_PNG).ConvertToBitmap(), &#8216;Save&#8217;, &#8221;)</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> toolbar.AddSeparator()</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> toolbar.AddSimpleTool(4, wx.Image(&#8217;stock_exit.png&#8217;, wx.BITMAP_TYPE_PNG).ConvertToBitmap(), &#8216;Exit&#8217;, &#8221;)</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> toolbar.Realize()</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> vbox.Add(toolbar, 0, border=5)</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> self.SetSizer(vbox)</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> self.statusbar = self.CreateStatusBar()</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> self.Centre()</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"><br />
self.Bind(wx.EVT_TOOL, self.OnNew, id=1)</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> self.Bind(wx.EVT_TOOL, self.OnOpen, id=2)</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> self.Bind(wx.EVT_TOOL, self.OnSave, id=3)</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> self.Bind(wx.EVT_TOOL, self.OnExit, id=4)</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;"><br />
def OnNew(self, event):</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> self.statusbar.SetStatusText(&#8216;New Command&#8217;)</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;"><br />
def OnOpen(self, event):</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> self.statusbar.SetStatusText(&#8216;Open Command&#8217;)</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;"><br />
def OnSave(self, event):</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> self.statusbar.SetStatusText(&#8216;Save Command&#8217;)</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;"><br />
def OnExit(self, event):</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> self.Close()</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;"><br />
class MyApp(wx.App):</span></p>
<p style="text-align: left; padding-left: 60px;"><span style="color: #0000ff;"> def OnInit(self):</span></p>
<p style="text-align: left; padding-left: 90px;"><span style="color: #0000ff;"> frame = MyToolBar(None, -1, &#8216;toolbar.py&#8217;)</span></p>
<p style="text-align: left; padding-left: 90px;"><span style="color: #0000ff;"> frame.Show(True)</span></p>
<p style="text-align: left; padding-left: 90px;"><span style="color: #0000ff;"> return True</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;"><br />
app = MyApp(0)</span></p>
<p style="text-align: left; padding-left: 30px;"><span style="color: #0000ff;">app.MainLoop()</span></p>
<pre style="text-align: left;"><span style="color: #ff0000;">
</span></pre>
<p><span style="color: #000000;">results in this (on Ubuntu):</span></p>
<div id="attachment_153" class="wp-caption aligncenter" style="width: 363px"><a href="http://www.cantinaconsulting.com/wp-content/toolbar.png"><img class="size-full wp-image-153" title="Ubuntu_wxpython_app" src="http://www.cantinaconsulting.com/wp-content/toolbar.png" alt="Resulting application in Ubuntu" width="353" height="263" /></a><p class="wp-caption-text">Resulting application in Ubuntu</p></div>
<p>While not much to look at, certainly, briefly think about what&#8217;s going on here. In ~45 lines of code, we have a fully functional application. It doesn&#8217;t do much,  yet, but imagine what we could do if you started hooking up some of your existing Python code, or hooking in some other Python modules. There&#8217;s a lot of power in this; the mind can hardly grasp the possibilities of, say, Windows apps powered by Python (take that, Visual Studio). I feel strongly that it has the potential to handle some serious projects, if given the opportunity.</p>
<p>This would be intensive, but I&#8217;m still learning wxPython myself. So far, it&#8217;s been great fun, and I highly recommend others to check it out. I&#8217;d love to see some examples out there of anyone who&#8217;s developed apps in the framework (a quick search doesn&#8217;t reveal much), and perhaps I&#8217;ll post some of my own as I start using it more.</p>
<p>Until then, try taking a look at wxPython.org (link) and the wxPython wiki (link). Give it a shot; I&#8217;m sure you&#8217;ll love it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2009/05/14/wxpython_first_impressions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Stephen Pember joins Cantina as Technical Principal</title>
		<link>http://www.cantinaconsulting.com/2009/04/27/stephen-pember-joins-cantina-as-technical-principal/</link>
		<comments>http://www.cantinaconsulting.com/2009/04/27/stephen-pember-joins-cantina-as-technical-principal/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 19:00:11 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[People]]></category>
		<category><![CDATA[newhire]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=140</guid>
		<description><![CDATA[Please join me in welcoming Stephen Pember as the newest Technical Principal Consultant at Cantina.  After a long and rather selective search, we&#8217;re very excited to bring Steve on board to increase our technical capabilities and to help us continue to deliver a great consulting experience to our clients.
Steve brings a wealth of experience [...]]]></description>
			<content:encoded><![CDATA[<p>Please join me in welcoming Stephen Pember as the newest Technical Principal Consultant at Cantina.  After a long and rather selective search, we&#8217;re very excited to bring Steve on board to increase our technical capabilities and to help us continue to deliver a great consulting experience to our clients.</p>
<p>Steve brings a wealth of experience to the table, including research in social network analysis and data mining during his Master&#8217;s at Tufts University, as well as extensive consulting experience delivering complex client projects in Flex/Flash, Java, Python, and PHP, to name a few.  </p>
<p>He&#8217;s been a great asset so far, as in the 3 weeks he&#8217;s been with us he&#8217;s brought in two new clients, helped us through crunch mode to launch a major project for one of our largest clients, and has begun restructuring our server architecture.  Not bad!</p>
<p>Read more about Steve and his experience on our <a href="http://www.cantinaconsulting.com/about/">About</a> page, or visit him on <a href="http://www.linkedin.com/in/spember">LinkedIn</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2009/04/27/stephen-pember-joins-cantina-as-technical-principal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web-based video on the iPhone sans Flash</title>
		<link>http://www.cantinaconsulting.com/2009/02/10/web-based-video-on-iphone-sans-flash/</link>
		<comments>http://www.cantinaconsulting.com/2009/02/10/web-based-video-on-iphone-sans-flash/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 15:44:04 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[RIA / Flash]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=108</guid>
		<description><![CDATA[Brightcove isn&#8217;t waiting around for Flash to be supported on the iPhone.  They&#8217;ve recently published an article in the help section of their web site which illustrates how easy it is to build web applications targeted for the iPhone using Brightcove&#8217;s Media API, without any server side code.
http://help.brightcove.com/developer/samples/iPhone/iPhone-portal.cfm
This sample application highlights a couple interest [...]]]></description>
			<content:encoded><![CDATA[<p>Brightcove isn&#8217;t waiting around for Flash to be supported on the iPhone.  They&#8217;ve recently published an article in the help section of their web site which illustrates how easy it is to build web applications targeted for the iPhone using Brightcove&#8217;s <a href="http://help.brightcove.com/developer/docs/mediaapi/media-API-getting-started.cfm">Media API</a>, without any server side code.</p>
<p><a href="http://help.brightcove.com/developer/samples/iPhone/iPhone-portal.cfm">http://help.brightcove.com/developer/samples/iPhone/iPhone-portal.cfm</a></p>
<p>This sample application highlights a couple interest points regarding the iPhone and Brightcove:</p>
<ul>
<li>Just because the iPhone doesn&#8217;t currently support Flash doesn&#8217;t mean that you can&#8217;t deliver high quality video via web applications.  Brightcove&#8217;s sample iPhone web application simply loads an h.264 encoded QuickTime into the iPhone browser which can be played through the iPhone&#8217;s built-in QuickTime video player.  No Flash needed.</li>
<li>With some fairly basic JavaScript, you can achieve functionality in a web application similar to native applications with support for clean and &#8220;touchable&#8221; menus, and orientation (portrait vs. landscape) detection</li>
<li>Brightcove&#8217;s RESTful <a href="http://help.brightcove.com/developer/docs/mediaapi/media-API-getting-started.cfm">Media API</a> provides a flexible way to incorporate videos published through their platform, without requiring a Flash video player</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2009/02/10/web-based-video-on-iphone-sans-flash/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Random Thoughts: Thick and Thin (Clients) and other Google-isms</title>
		<link>http://www.cantinaconsulting.com/2009/02/04/random-thoughts-thick-and-thin-clients-and-other-google-isms/</link>
		<comments>http://www.cantinaconsulting.com/2009/02/04/random-thoughts-thick-and-thin-clients-and-other-google-isms/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 15:53:00 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=105</guid>
		<description><![CDATA[At Cantina, we use Google in practically everything we do.  We make heavy use of Google Apps for Domains to manage our email, calendars, and internal documentation.  YouTube is a constant distraction, er, research tool.  Some of us share photos via Picasa.  SketchUp can be a handy tool for working on [...]]]></description>
			<content:encoded><![CDATA[<p>At Cantina, we use Google in practically everything we do.  We make heavy use of <a href="https://www.google.com/a/">Google Apps for Domains</a> to manage our email, calendars, and internal documentation.  YouTube is a constant distraction, er, research tool.  Some of us share photos via <a href="http://picasa.google.com/">Picasa</a>.  SketchUp can be a handy tool for working on <a href="http://www.wonderhowto.com/how-to/video/how-to-create-a-poker-game-in-sketchup-256990/">game development</a>.  And every once in a while, we have to do a Google search (yes even we sometimes have to look things up).</p>
<p>As time marches on, it is becoming clearer that Google is focusing on the browser as the primary application development platform.  This is evident with their release of <a href="http://www.google.com/chrome">Chrome</a>, their first foray into the browser market which attempts to make browsing faster and more reliable, and even more clear with the more recent news that Google has managed to get <a href="http://googlesystem.blogspot.com/2009/01/offline-gmail.html">Gmail to work offline</a>, with the use of <a href="http://gears.google.com/">Google Gears</a>.</p>
<p>While I find the ability to have a fully browser-based application running offline impressive, my first thought upon hearing such news is: why?  I may be old fashioned, but I still use an actual email client to read my mail (Apple’s Mail application).  I’ve been able to read my mail offline for as long as I can remember.  Mail clients have been around for years (decades?) and have been admirably solving the problem of reading and writing email for a long time.  I realize that web-based email simplifies the process of reading and writing email by not requiring you to have to configure an email program with the necessary settings.  But what about the other issues that make it a challenge?  Being a developer, my browser is always crashing (and sometimes it’s not even my fault).  Flash 10 on the Mac, for example, is constantly having me reload my Firefox instance and trying to pick up where I left off.  This makes the browser an undesirable place to keep my email open.  </p>
<p>Beyond Gmail, I must say that I’ve been burned enough times in writing long form content, be it emails, or blog posts, or bug reports, you name it, that I’m cautious and reluctant to do that in a browser.  I’m a keyboard shortcut guy, and on the Mac, many times the go to beginning of line, or go to end of line key commands actually force the browser to hit the back button.  I’ve lost a lot of work this way (my own fault), but the key command is a system standard, and the browser breaks that.  In fact, I’m writing this blog post in an offline application, to later cut and paste it into our blogging system.  </p>
<p>I’d also put web-based instant messaging into the category of “why do we need this in browser as well”.   There has been a proliferation of web-based instant messaging, with <a href="http://www.google.com/talk/">Google Talk</a> and <a href="http://www.facebook.com">Facebook</a>, which requires me to hunt down the appropriate tab in Firefox to see what people are writing to me.  This makes the whole instant messaging process far less “instant”.   </p>
<p>So while all of what I have just mentioned might make me an oddball in the Web 2.0 world, where many (most) people I know read their email in the browser and have a Facebook window open at all waking hours, I have to take a moment to realize the lesson here.  If history has taught us anything, it has taught us that the most technically correct or appropriate solution is not always (or rarely is) the solution that ultimately becomes successful, or popular.  Take MySpace for example.  The user experience is arguably miserable, yet MySpace paved the way for large scale adoption of social networking.  Just because I think that my trusty old email client, which I have been using for years, can already do what Gmail’s miraculous new offline feature can do, and better, I have to appreciate the significance to the throngs of people that use Gmail via the browser and have never looked back.</p>
<p>P.S.</p>
<p>In other Google news, I must say I was excited to find that the defunct JotSpot blogging platform, which has consumed by Google has made its way into <a href="http://sites.google.com/">Google Sites</a>.  I was a fan of JotSpot wikis back in the day, and Google’s transformation of the product seems like a great addition to the product line.  </p>
<p>In other news, if you’ve ever used another one of Google’s acquisitions that goes by the name of <a href="http://googlesystem.blogspot.com/2009/01/grandcentral-20-almost-ready-to-be.html">GrandCentral</a>, it’s coming back and I’m looking forward to see what has been done to it.</p>
<p>To round out the Google rumor round up, there have been hints of a <a href="http://googlesystem.blogspot.com/2009/01/more-signs-of-google-webdrive.html">Google Web Drive</a>.  This seems like a natural progression in their cloud-based computing offerings.  I’m an avid user of <a href="http://www.jungledisk.com">Jungle Disk</a> so I’m curious to see what Google can whip up.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2009/02/04/random-thoughts-thick-and-thin-clients-and-other-google-isms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Job Opportunity at Cantina</title>
		<link>http://www.cantinaconsulting.com/2009/01/23/job-opportunity-at-cantina/</link>
		<comments>http://www.cantinaconsulting.com/2009/01/23/job-opportunity-at-cantina/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 16:03:51 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[People]]></category>
		<category><![CDATA[career]]></category>
		<category><![CDATA[job]]></category>
		<category><![CDATA[jobs]]></category>
		<category><![CDATA[open position]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=103</guid>
		<description><![CDATA[While I know some of us are sitting around waiting for our bailout checks, at Cantina we&#8217;re doing our part to stimulate the economy.  We&#8217;re looking for someone with incredible technical skills and a real passion for programming.  You&#8217;ve got to have the personal skills to please our clients and always over deliver.  You should [...]]]></description>
			<content:encoded><![CDATA[<p>While I know some of us are sitting around waiting for our bailout checks, at Cantina we&#8217;re doing our part to stimulate the economy.  We&#8217;re looking for someone with incredible technical skills and a real passion for programming.  You&#8217;ve got to have the personal skills to please our clients and always over deliver.  You should know it&#8217;s not about your favorite technology, but the right technology for the job.  If you&#8217;re tired of the same old legacy projects and want to challenge yourself with a really talented team of individuals and create amazing web applications, than take a look at our job posting:</p>
<p><a href="http://www.linkedin.com/jobs?viewJob=&amp;jobId=647499">http://www.linkedin.com/jobs?viewJob=&amp;jobId=647499</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2009/01/23/job-opportunity-at-cantina/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sync Soup or another case for unified online identity</title>
		<link>http://www.cantinaconsulting.com/2008/12/10/sync-soup-or-another-case-for-unified-online-identity/</link>
		<comments>http://www.cantinaconsulting.com/2008/12/10/sync-soup-or-another-case-for-unified-online-identity/#comments</comments>
		<pubDate>Wed, 10 Dec 2008 19:12:52 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Productivity]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/2008/12/10/sync-soup-or-another-case-for-unified-online-identity/</guid>
		<description><![CDATA[As a software engineer, I find that I apply basic software engineering principles to all aspects of my life, and a big one is the &#8220;don&#8217;t repeat yourself&#8221; philosophy, or DRY.  Nowhere have I felt more pain on this lately than with trying to solve the problem of a unified email, calendar, and contact [...]]]></description>
			<content:encoded><![CDATA[<p>As a software engineer, I find that I apply basic software engineering principles to all aspects of my life, and a big one is the &#8220;don&#8217;t repeat yourself&#8221; philosophy, or DRY.  Nowhere have I felt more pain on this lately than with trying to solve the problem of a unified email, calendar, and contact solution that is available to me wherever I am.  Let me state the problem more clearly:</p>
<p>At Cantina, we make heavy use of all that Google Apps has to offer to provide a cost effective, yet extremely functional solution to email (both web-based and IMAP) and shared calendars.  This, for the most part, suits our needs adequately and with minimal cost and maintenance.  Now, throw into this scenario the fact that we are consultants, and as such end up making heavy use of our clients&#8217; respective email and shared calendar solutions, most if not all of which are handled via Microsoft Exchange Server.  There are a whole host of reasons why this is a good thing for our clients, however this presents a problem for someone like myself, who likes to keep everything in one place, depending on where I am:</p>
<ol>
<li>If I&#8217;m at my desk, I want it on my Mac laptop and want all of my email managed via Apple&#8217;s Mail application, and all of my calendar managed through iCal</li>
<li>If I&#8217;m out and about, I want it all on my iPhone (you can see my brand allegiance here &#8211; not a fanboy just like low maintenance and high integration)</li>
<li>If I&#8217;m really in a pickle and don&#8217;t have my laptop or my iPhone (this is rare), but still have internet, it would be ideal to have a unified web interface to get to all of this stuff, perhaps via Google Apps.  Again this is a rare case.</li>
</ol>
<p>Now, there are a myriad of synchronization technologies and solutions out there that attempt to bridge the gaps between these various components, such as:</p>
<ul>
<li>IMAP: Apple Mail &#8211; Google Apps Mail &amp; Gmail (works great apart from the lack of <a href="http://www.polaine.com/playpen/2008/05/26/apple-mail-folder-subscriptions-and-gmail-imap/" title="Playpen  &raquo; Blog Archive   &raquo; IMAP folder subscriptions with GMail and Apple Mail">Label/Folder IMAP subscription</a>)</li>
<li>Apple Mail&#8217;s Exchange Support: Apple Mail &#8211; Exchange (still requires IMAP to be enabled, which isn&#8217;t always the case)</li>
<li><a href="http://spanningsync.com/" title="Spanning Sync - Sync iCal and Google Calendar">Spanning Sync</a>: Google Calendar/Contacts &#8211; iCal/Address Book</li>
<li>Entourage with Sync Services: Exchange Calendar/Contacts &#8211; iCal/Address Book (issues with multiple exchange accounts)</li>
<li><a href="http://www.nuevasync.com/" title="NuevaSync - Over the Air Synchronization">NuevaSync</a>: Google Calendar &#8211; iPhone (over the air, doesn&#8217;t require cable, yet takes up your only Exchange account on the iPhone)</li>
<li>Active Sync on the iPhone: Exchange &#8211; iPhone (over the air, but only supports one Exchange account at a time)
<li>And so on&#8230;</li>
</ul>
<p>All of these little &#8220;bridges&#8221; spanning the gaps between various applications each have their own small set of problems and limitations which makes this whole sync ecosystem break down.  What&#8217;s worse, is that sometimes, attempting to make this work can have unintended or potentially disastrous consequences (Imagine all your calendar events from one client syncing onto another client&#8217;s Exchange server).</p>
<p>So there&#8217;s the problem, but what is the solution?  For many people, a single Exchange or <a href="http://www.apple.com/mobileme/" title="Apple - MobileMe">Mobile Me</a> account will do the trick, but for me (a consultant using multiple services), it does not.  Sure, there are some glimmers of hope.  Apple is <a href="http://www.apple.com/macosx/snowleopard/" title="Apple - Mac OS X Leopard - Snow Leopard">bolstering their Exchange support</a> in their applications following the introduction of Active Sync to the iPhone.  Sure, there might be a day soon when the iPhone supports multiple Exchange accounts and can subscribe to <a href="http://lifehacker.com/399366/google-calendar-adds-caldav-support-enabling-ical-sync" title="Google Calendar: Google Calendar Adds CalDAV Support, Enabling iCal Sync">CalDAV on Google</a>.  </p>
<p>These are all patches to a solution that lacks a holistic view of the problem.  Where have we seen this before?  How about a unified login?  <a href="http://openid.net/what/" title="OpenID   &raquo; What is OpenID?">OpenID</a> attempts to solve the real and very present problem of managing separate authentication credentials across the vast ocean of sites requiring registration on the web.  Though it&#8217;s not quite a homerun yet, there&#8217;s progress being made.  Any standard will run into this issue, even <a href="http://www.sitepoint.com/blogs/2008/01/23/ie8-standards-mode-is-opt-in/" title="SitePoint &raquo; IE8 Standards Mode Is Opt-in">HTML</a>.  </p>
<p>The questions here are these: Can we extend this concept of online identity beyond logging into sites?  Can we aggregate our various online presence (including email &amp; calendars) to our one true e-self?  I think the answer is yes, but in time, and I think Apple&#8217;s lowly Address Book application, the humble servant of contact management on the Mac may serve as an example.  You see, in Address Book, there is a particular contact card that is designated as &#8220;Me&#8221;, the current user.  In this contact card, I can add any number of phone numbers, fax numbers, etc., but more importantly I can add multiple email addresses and IM screen names, which all are identified as &#8220;Me&#8221;.  This means that no matter what email address in Apple Mail I use to send or receive email, if it&#8217;s in my &#8220;Me&#8221; card, the system knows it&#8217;s &#8220;Me&#8221;.  I think that this very basic approach can be extended to aggregate online identity at a much higher and more meaningful level, across the various services I might use as a result of my online existence.  Now we just have to agree on what that will look like, and if history has taught us anything, <a href="http://www.internetevolution.com/document.asp?doc_id=162411&amp;print=yes" title="Internet Evolution - The Big Report - One Web, One Web ID">it won&#8217;t happen fast</a>. </p>
<p>Thoughts?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/12/10/sync-soup-or-another-case-for-unified-online-identity/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>while we&#8217;ve got your eyes&#8230;</title>
		<link>http://www.cantinaconsulting.com/2008/11/18/while-weve-got-your-eyes/</link>
		<comments>http://www.cantinaconsulting.com/2008/11/18/while-weve-got-your-eyes/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 19:42:35 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[crowdspring]]></category>
		<category><![CDATA[logo]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=61</guid>
		<description><![CDATA[take a look at our potential logos as they unfold. let us know what you think, and feel free to submit comments or rate the submissions.
]]></description>
			<content:encoded><![CDATA[<p>take a look at our <a href="http://www.crowdspring.com/projects/graphic_design/logo/logo_for_boutique_web_applications_consulting_firm">potential logos</a> as they unfold. let us know what you think, and feel free to submit comments or rate the submissions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/11/18/while-weve-got-your-eyes/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>specious?</title>
		<link>http://www.cantinaconsulting.com/2008/11/18/specious/</link>
		<comments>http://www.cantinaconsulting.com/2008/11/18/specious/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 19:37:54 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=58</guid>
		<description><![CDATA[Here comes a cat out of a bag &#8211; we&#8217;re in the process of building out our brand. Every growing company faces this challenge at some point, and so Cantina finds itself in the thick of it.

As purveyors of tech that, at least in theory, increases social interaction and the power of community, we&#8217;ve decided [...]]]></description>
			<content:encoded><![CDATA[<div>Here comes a cat out of a bag &#8211; we&#8217;re in the process of building out our brand. Every growing company faces this challenge at some point, and so Cantina finds itself in the thick of it.</div>
<div>
<div>As purveyors of tech that, at least in theory, increases social interaction and the power of community, we&#8217;ve decided to walk our walk and dip our toes in a bit of the crowd-sourcing pool and see what kind of logo we could fish out. There are a number of these services available, we&#8217;ve chosen to give <a href="http://www.crowdspring.com/" target="new">Crowdspring</a> a day in court. The results thus far have been wide-ranging; clearly this crowd is a heterogenous one.</div>
<div>What&#8217;s been really interesting, from my POV, is the controversy this approach stirs amongst those in the design community. The rub seems to lay not in crowd-sourcing, but rather in the notion of speculative work, or &#8220;exert your effort and maybe I&#8217;ll bite&#8221;. Imagine using this approach for other day to day transactions? Having someone paint your house *before* paying them? &#8220;No, sorry, I don&#8217;t like it. Thanks anyway.&#8221; After a chef has prepared your dinner? &#8220;That looks tempting enough, but I think I&#8217;ll pass.&#8221; Turns things upside down a bit no?</div>
<div>A designer and colleague of ours, Kurt Zinser of <a href="http://www.methodbureau.com" target="new">Method Bureau</a>, says, spec work is &#8220;harmful to the profession, encourages sub-par work and turns the practice into a commodity,&#8221; and pointed me to this statement from <a href="http://www.aiga.org/content.cfm/position-spec-work" target="new">AIGA</a>: </div>
<div>
<div>&#8220;AIGA believes that doing speculative work seriously compromises the quality of work that clients are entitled to and also violates a tacit, long-standing ethical standard in the communication design profession worldwide. AIGA strongly discourages the practice of requesting that design work be produced and submitted on a speculative basis in order to be considered for acceptance on a project.&#8221; They even provide a <a href="http://www.aiga.org/resources/content/3/5/9/9/documents/aiga_standard_specletter.doc" target="new">sample response letter</a> that further explains their position.</div>
<div>I&#8217;m sure there are those skeptics out there who will naturally counter that of course AIGA would seek to protect itself and the interests of its members; what representative organization wouldn&#8217;t? Beyond the obvious then, I think the AIGA argument has merit. Many specialized crafts have and are dealing with these same pressures &#8211; the commoditization of one&#8217;s long honed skill.</div>
<div><a href="http://andrewhyde.net/">Andrew Hyde</a> has some strong feelings too, particularly <a href="http://andrewhyde.net/spec-work-is-evil-why-i-hate-crowdspring/" target="new">regarding Crowdspring</a> itself:</div>
<div>It appears the controversy is tied to the idea of speculative work versus the notion of crowd-sourcing. Is there a better way, a solution with positive impact  for both sides of the divide?</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/11/18/specious/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Joining Cantina</title>
		<link>http://www.cantinaconsulting.com/2008/11/11/joining-cantina/</link>
		<comments>http://www.cantinaconsulting.com/2008/11/11/joining-cantina/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 20:46:43 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[People]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=52</guid>
		<description><![CDATA[I thought I would sit down and write my first post by thanking the team at Cantina for the opportunity to work with them.  I&#8217;ve only been here two weeks and I already know I&#8217;m working with the best teams on the planet.  As I met with many of their clients over the [...]]]></description>
			<content:encoded><![CDATA[<p>I thought I would sit down and write my first post by thanking the team at Cantina for the opportunity to work with them.  I&#8217;ve only been here two weeks and I already know I&#8217;m working with the best teams on the planet.  As I met with many of their clients over the last few weeks, I&#8217;ve heard nothing but praise for the work they do. </p>
<p>As we face the challenges of the coming year, with a tough economy, it&#8217;s good to know that you&#8217;re with a group of people that can really get the job done.  My wish for the next few months is to take on the task of supporting each of our clients as they try to navigate our current financial situation, but also find new opportunities and business; so the team here can continue to do what they do best, deliver amazing applications on time and under budget.   </p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/11/11/joining-cantina/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Carm Huntress Joins Cantina as a Business Development Principal.</title>
		<link>http://www.cantinaconsulting.com/2008/11/06/carm-huntress-joins-cantina-as-a-business-development-principal/</link>
		<comments>http://www.cantinaconsulting.com/2008/11/06/carm-huntress-joins-cantina-as-a-business-development-principal/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 20:16:33 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[People]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=41</guid>
		<description><![CDATA[Please join me in welcoming Carm Huntress, the newest partner at Cantina Consulting, as a Business Development Principal.
With a deep passion for technology, new business innovations and web applications, Carm brings insight and creative ideas to any project. Leading Sales and Business Development, he works to match client needs directly with the right team at [...]]]></description>
			<content:encoded><![CDATA[<p>Please join me in welcoming Carm Huntress, the newest partner at Cantina Consulting, as a Business Development Principal.</p>
<p>With a deep passion for technology, new business innovations and web applications, Carm brings insight and creative ideas to any project. Leading Sales and Business Development, he works to match client needs directly with the right team at Cantina.</p>
<p>We’re excited to have Carm as a partner as Cantina continues to grow.</p>
<p>Feel free to read Carms’ bio in the About section.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/11/06/carm-huntress-joins-cantina-as-a-business-development-principal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Election tech</title>
		<link>http://www.cantinaconsulting.com/2008/10/31/election-tech/</link>
		<comments>http://www.cantinaconsulting.com/2008/10/31/election-tech/#comments</comments>
		<pubDate>Fri, 31 Oct 2008 21:11:06 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[e-voting]]></category>
		<category><![CDATA[election]]></category>
		<category><![CDATA[election technology]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=37</guid>
		<description><![CDATA[Here it is, the spookiest night of the year and the prospect of another election day debacle is about as frightening a prospect as any. And why shouldn&#8217;t we be scared? What&#8217;s really changed in the past 8 years in regards to the process of voting? In 2000, the death of the chad pappy, the [...]]]></description>
			<content:encoded><![CDATA[<p>Here it is, the spookiest night of the year and the prospect of another election day debacle is about as frightening a prospect as any. And why shouldn&#8217;t we be scared? What&#8217;s really changed in the past 8 years in regards to the process of voting? In 2000, the death of the chad pappy, the paper ballot, was all but assured. Now we&#8217;re 8 years later, the iPod of then is now the doorstop of today, we&#8217;ve got touch-based computing in our pockets, we can sign, seal and deliver nearly every bit of life&#8217;s required documents digitally and yet&#8230; The voting process is still antiquated and unsolved. How is it that we can file our taxes &#8211; transmitting uber-sensitive data over the ether, yet can&#8217;t send a simple authenticated vote? Where is the open source movement to solve this issue? Clearly we can&#8217;t allow one or two vendors (the Republican Voting Company&#8230; err Diebold comes to mind). Surely this is a problem that can be solved.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/10/31/election-tech/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GORM multiple datasource access</title>
		<link>http://www.cantinaconsulting.com/2008/10/24/gorm-multiple-datasource-access/</link>
		<comments>http://www.cantinaconsulting.com/2008/10/24/gorm-multiple-datasource-access/#comments</comments>
		<pubDate>Fri, 24 Oct 2008 16:19:41 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Groovy on Grails]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=36</guid>
		<description><![CDATA[It appears that the limitations of Grails object relational mapping (GORM) &#8211; only allowing connections to a single datasource &#8211; has been resolved with a new plugin from Burt Beckwith.  This feature which allows application architects to design systems that can shard data across federated databases has been around for awhile in ActiveRecord &#8211; [...]]]></description>
			<content:encoded><![CDATA[<p>It appears that the limitations of Grails object relational mapping (GORM) &#8211; only allowing connections to a single datasource &#8211; has been resolved with a <a href="http://burtbeckwith.com/blog/?p=70">new plugin</a> from Burt Beckwith.  This feature which allows application architects to design systems that can shard data across federated databases has been around for awhile in ActiveRecord &#8211; Rails object relational mapping framework. So it is good to see someone has addressed the issue.  I hope to try it out soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/10/24/gorm-multiple-datasource-access/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adobe Releases Flash 10 Player</title>
		<link>http://www.cantinaconsulting.com/2008/10/24/adobe-releases-flash-10-player/</link>
		<comments>http://www.cantinaconsulting.com/2008/10/24/adobe-releases-flash-10-player/#comments</comments>
		<pubDate>Fri, 24 Oct 2008 13:17:47 +0000</pubDate>
		<dc:creator>chris</dc:creator>
				<category><![CDATA[RIA / Flash]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=35</guid>
		<description><![CDATA[Flash 1&#8230; 2&#8230; 3&#8230; 4&#8230; 5&#8230; MX&#8230; MX 2004&#8230; 8&#8230; 9&#8230; &#8230; &#8230; and now? Just &#8220;10&#8243;. nice and easy.
The latest and greatest from Adobe includes support for native 3D (bring on more carousel views), &#8220;inverse kinematics&#8220;, jointed assets that react intelligently to each other when animated (see PrayStation circa &#8216;99?). Additionally, they promise advanced [...]]]></description>
			<content:encoded><![CDATA[<p>Flash 1&#8230; 2&#8230; 3&#8230; 4&#8230; 5&#8230; MX&#8230; MX 2004&#8230; 8&#8230; 9&#8230; &#8230; &#8230; and now? Just &#8220;10&#8243;. nice and easy.</p>
<p>The latest and greatest from Adobe includes support for native 3D (bring on more carousel views), &#8220;<a href="http://en.wikipedia.org/wiki/Inverse_kinematics" target="_blank">inverse kinematics</a>&#8220;, jointed assets that react intelligently to each other when animated (see PrayStation circa &#8216;99?). Additionally, they promise advanced text rendering and control (again), dynamic sound gen, and an yet another &#8220;advanced&#8221; drawing API. How about animating rounded corner masks? What will this all bring? The resurgence of the intro skip or further along the never ending path to a &#8220;richer experience&#8221;. we&#8217;ll see&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/10/24/adobe-releases-flash-10-player/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pivot UI Toolkit 1.0 Released</title>
		<link>http://www.cantinaconsulting.com/2008/10/21/pivot-ui-toolkit-10-released/</link>
		<comments>http://www.cantinaconsulting.com/2008/10/21/pivot-ui-toolkit-10-released/#comments</comments>
		<pubDate>Tue, 21 Oct 2008 19:00:33 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[RIA / Flash]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=34</guid>
		<description><![CDATA[Our good friend and former colleague Greg Brown has just recently launched the first official 1.0 release of the  open source Pivot Toolkit.  The Pivot Toolkit provides Java developers a great new way to build applications with rich user interfaces that can be easily deployed both to web users and to desktop users. [...]]]></description>
			<content:encoded><![CDATA[<p>Our good friend and former colleague <a href="http://weblogs.java.net/blog/gkbrown/" title="Greg Brown's Blog">Greg Brown</a> has just recently launched the first official 1.0 release of the  open source <a href="http://pivot-toolkit.org/" title="Pivot Toolkit">Pivot Toolkit</a>.  The Pivot Toolkit provides Java developers a great new way to build applications with rich user interfaces that can be easily deployed both to web users and to desktop users.  </p>
<p>
Pivot harnesses the power of the Java2D API and packages it in a toolkit that offers these benefits:
</p>
<ul>
<li>MVC architecture to separate controller logic from the view layer</li>
<li>XML-based markup (WTKX) to design views including CSS-like style definition</li>
<li>Easy integration with remote web data services</li>
<li>Built-in charting capabilities based on JFreeChart</li>
</ul>
<p>
Check it out: <a href="http://pivot-toolkit.org/" title="Pivot Toolkit">http://pivot-toolkit.org/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/10/21/pivot-ui-toolkit-10-released/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fitting Grails into an Ant Build Environment</title>
		<link>http://www.cantinaconsulting.com/2008/09/01/fitting-grails-into-an-ant-build-environment/</link>
		<comments>http://www.cantinaconsulting.com/2008/09/01/fitting-grails-into-an-ant-build-environment/#comments</comments>
		<pubDate>Mon, 01 Sep 2008 17:41:54 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Groovy on Grails]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=33</guid>
		<description><![CDATA[I&#8217;ve been working on a project that involves rolling a Grails-based application into a much larger build process, one which ties together several Java components and test suites through an Ant build process.  This integration involves Ant calling the Grails command line tasks (clean, test-app, war, etc).  The standard build.xml that is found [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a project that involves rolling a Grails-based application into a much larger build process, one which ties together several Java components and test suites through an <a href="http://ant.apache.org">Ant</a> build process.  This integration involves Ant calling the Grails command line tasks (clean, test-app, war, etc).  The standard build.xml that is found after creating a new Grails application currently uses the <em>exec</em> task to invoke the command line tasks.  While this works, it takes you out of the world of Ant (and consequently out of the world of Java).</p>
<p>Fortunately, for a little while now, the Grails distribution has been packaged with an Ant macro, graciously contributed by <a href="http://www.linkedin.com" title="Linked In">LinkedIn</a>, which allows you to more tightly integrate Grails tasks with an Ant build.  You can find the script here:</p>
<p><a href="http://svn.codehaus.org/grails/trunk/grails/src/grails/grails-macros.xml" title="grails-macros.xml">http://svn.codehaus.org/grails/trunk/grails/src/grails/grails-macros.xml</a></p>
<p>
This macro sets up a Java environment using the GrailsStarter and GrailsScriptRunner bootstrap classes to startup a Grails environment and execute the given Grails <a href="http://groovy.codehaus.org/Gant" title="Groovy - Gant">Gant</a> script.  This is similar to the way the Grails command line batch/shell scripts function, however the macro does it within an Ant <a href="http://ant.apache.org/manual/CoreTasks/java.html" title="Java Task">java</a> task, which allows us to add additional information to the JVM as it executes, such as additional classpath information, system properties, and JVM arguments to name a few.
</p>
<p>
You can use this macro by importing it into your Ant build script and invoking it as follows (assuming your GRAILS_HOME environment variable is set properly):
</p>
<pre>
&lt;import file=&quot;${env.GRAILS_HOME}/src/grails/grails-macros.xml&quot; /&gt;

&lt;grails command=&quot;clean&quot; /&gt;
&lt;grails command=&quot;war&quot; args=&quot;mywarfile.war&quot;/&gt;
...
</pre>
<p>
This is certainly handy but doesn&#8217;t offer much beyond using Ant&#8217;s <a href="http://ant.apache.org/manual/CoreTasks/exec.html" title="Exec Task">exec</a> task.  However, once we look at what we can pass into the macro, the added value becomes more apparent.  The macro accepts several argument attributes and elements to augment the way the macro executes.  The example below shows how we can add additional system properties and classpath items to a <i>run-app</i> command.
</p>
<pre>
&lt;grails command=&quot;run-app&quot;&gt;
  &lt;sysprops&gt;
    &lt;sysproperty key=&quot;server.port&quot; value=&quot;9999&quot; /&gt;
  &lt;/sysprops&gt;
  &lt;extend-classpath&gt;
    &lt;pathelement location=&quot;SOME_OTHER_LIB_LOCATION/foo.jar&quot;/&gt;
    &lt;pathelement location=&quot;SOME_OTHER_LIB_LOCATION/bar.jar&quot;/&gt;
  &lt;/extend-classpath&gt;
&lt;/grails&gt;
</pre>
<p>
This example shows that we can add in system properties to specify to things like the <i>server.port</i> value for the <i>run-app</i> command.  In this example it is hardcoded, however in most non-trivial Ant build processes, this would be specified via properties file or some other mechanism to provide values that are specific to the build environment in question (e.g., development, test, integration, production).
</p>
<p>
What&#8217;s more interesting in this example is that we&#8217;ve added additional elements to the classpath which then get passed along to the Ant java task.  This provides tremendous flexibility to include items in the classpath that do not appear in the standard Grails locations like these:
</p>
<ul>
<li>GRAILS_HOME\dist</li>
<li>GRAILS_HOME\lib</li>
<li>PROJECT_HOME\lib</li>
</ul>
<p>
This flexibility allows for other build artifacts in an Ant build process to be dynamically included into the Grails runtime from other locations in the build process.
</p>
<p>
It should be said that I&#8217;ve had to make some modifications to the macro in order to tailor it to my needs as well as to get it working properly across environments. You can see the changes I&#8217;ve made <a href="http://files.cantinaconsulting.com/grails-macros.xml">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/09/01/fitting-grails-into-an-ant-build-environment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Chris Lamothe joins Cantina as User Experience Principal</title>
		<link>http://www.cantinaconsulting.com/2008/05/01/chris-lamothe-joins-cantina-as-user-experience-principal/</link>
		<comments>http://www.cantinaconsulting.com/2008/05/01/chris-lamothe-joins-cantina-as-user-experience-principal/#comments</comments>
		<pubDate>Thu, 01 May 2008 16:33:40 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[People]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/2008/05/01/chris-lamothe-joins-cantina-as-user-experience-principal/</guid>
		<description><![CDATA[Please join me in welcoming Chris Lamothe, the newest partner at Cantina Consulting, as a User Experience Principal.
Chris brings nearly 10 years of experience in a variety of aspects of user-centric design and interactive development, with specific areas of focus in e-learning and Rich Internet Application (RIA) design and development.
Both Matt and I have worked [...]]]></description>
			<content:encoded><![CDATA[<p>Please join me in welcoming Chris Lamothe, the newest partner at Cantina Consulting, as a User Experience Principal.</p>
<p>Chris brings nearly 10 years of experience in a variety of aspects of user-centric design and interactive development, with specific areas of focus in e-learning and Rich Internet Application (RIA) design and development.</p>
<p>Both Matt and I have worked alongside Chris in the past, during consulting engagements at Molecular as well as a variety of side projects over the years. We&#8217;re thrilled to have Chris a partner as Cantina continues to grow.</p>
<p>Feel free to read Chris&#8217; bio in the <a href="/about">About</a> section.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/05/01/chris-lamothe-joins-cantina-as-user-experience-principal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gotchas in using BackgrounDRb in Ruby on Rails</title>
		<link>http://www.cantinaconsulting.com/2008/04/22/gotchas-in-using-backgroundrb-in-ruby-on-rails/</link>
		<comments>http://www.cantinaconsulting.com/2008/04/22/gotchas-in-using-backgroundrb-in-ruby-on-rails/#comments</comments>
		<pubDate>Wed, 23 Apr 2008 03:02:12 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/2008/04/22/gotchas-in-using-backgroundrb-in-ruby-on-rails/</guid>
		<description><![CDATA[I&#8217;ve been working on a bit of code to perform audio and video encoding for media files uploaded to one of our client&#8217;s sites and I was thrilled to come across BackgrounDRb, a Rails plugin that allows developers to build scheduled background tasks, similar to the OpenSympony&#8217;s Quartz for Java. The plugin also allows you [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a bit of code to perform audio and video encoding for media files uploaded to one of our client&#8217;s sites and I was thrilled to come across BackgrounDRb, a Rails plugin that allows developers to build scheduled background tasks, similar to the OpenSympony&#8217;s <a href="http://www.opensymphony.com/quartz/">Quartz</a> for Java. The plugin also allows you to allow user actions to initiate long running processes by spawning worker threads from controllers (or other places).</p>
<p>Of particular interest to me was the ability to spawn (fork) worker threads from user actions, or in this case, ActiveRecord callbacks which were called when the user action caused my model object to be saved. The basic order of operations is this:</p>
<ol>
<li>User uploads an audio file</li>
<li>Uploaded file data is loaded into an attachment_fu model object</li>
<li>Model object is saved</li>
<li>Model object&#8217;s after_save callback is called</li>
<li>The after_save callback determines whether the uploaded file requires encoding, and spawns a BackgrounDRb worker process if it does</li>
</ol>
<p>In this process lay many issues. I&#8217;ve attempted to describe some of them below.</p>
<p><strong>Close your connections</strong></p>
<p>This may be obvious to many, but I figured with all that ActiveRecord does for you, that if I do some work with ActiveRecord in a BackgrounDRB worker process, my database connections would be closed automatically. This was not the case, however it can be quickly remedied by adding the following after all your code is done doing what it needs to do:</p>
<p>ActiveRecord::Base.connection.disconnect!</p>
<p><strong>Don&#8217;t try to pass entire ActiveRecord objects to workers from Rails</strong></p>
<p>I started building a simple call to spawn a new BackgrounDRb worker from an ActiveRecord lifecycle callback method (see below), and starting running into errors like these:</p>
<pre>
undefined method `[]' for #&lt;DRb::DRbUnknown:0x2501bd4&gt;
</pre>
<p></p>
<p>I found a number of postings online indicating that simply adding the following to my model objects would clear this up:</p>
<pre>
include DRbUndumped
</pre>
<p>Doing so did not fix my undefined method problems, so when I came across this on another blog, I decided to cut my losses and just pass the database ID.</p>
<blockquote>
<p><span style="font-weight: normal;">When passing arguments from Rails to BackgrounDRb workers, don’t pass huge ActiveRecord objects. Its asking for trouble. You can easily circumvent the situation by passing id of AR objects.<a href="http://gnufied.org/2008/02/12/backgroundrb-best-practises/"></a></span></p>
<p>From: <a href="http://gnufied.org/2008/02/12/backgroundrb-best-practises/">BackgrounDRb best practises</a></p>
</blockquote>
<p>One thing that I didn&#8217;t think I&#8217;d be dealing with in coming to Rails from a Java background is serialization issues, but there we have it.</p>
<p><strong>Don&#8217;t create new workers from new record callbacks</strong></p>
<p>This may have been common knowledge, but I had to discover this the hard way. The after_save callback in ActiveRecord model objects is called before the save transaction has been committed. The implication this has is that if I pass an ID of an ActiveRecord object to BackgrounDRb for further processing, strange things can happen.</p>
<p>In the case of my after_save callback being called on a newly created object, I found that most of the time, by the time the BackrounDRb process starts working and tries to retrieve the object using the ID I have passed, my original object.save() transaction has not yet committed, so I get errors indicating the record could not be found, even though I check the database no more than a second later and the record is there and intact.<br />
It seems that I&#8217;m not the only one that was looking for a post-commit callback:</p>
<ul>
<li><a href="http://elimiller.blogspot.com/2007/06/proper-cache-expiry-with-aftercommit.html">Proper cache expiry with after_commit</a><a href="http://localhost3000.de/2008/02/12/a-good-thing-to-know-after_save-sits-inside-the-transaction/"></a></li>
<li><a href="http://localhost3000.de/2008/02/12/a-good-thing-to-know-after_save-sits-inside-the-transaction/">A good thing to know: after_save sits inside the transaction</a></li>
</ul>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/04/22/gotchas-in-using-backgroundrb-in-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Happenings</title>
		<link>http://www.cantinaconsulting.com/2008/02/07/happenings/</link>
		<comments>http://www.cantinaconsulting.com/2008/02/07/happenings/#comments</comments>
		<pubDate>Wed, 06 Feb 2008 18:33:10 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/2008/02/07/happenings/</guid>
		<description><![CDATA[There&#8217;s been a bit of radio silence on our blog lately, and it&#8217;s for good reason!&#160; We&#8217;ve been busy on several Rails and Grails-based projects lately which is why we&#8217;re very excited about the releases of both Rails 2.0.x and the first full 1.0 release of the Grails framework.&#160;
The Grails release in particular is significant [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been a bit of radio silence on our blog lately, and it&#8217;s for good reason!&nbsp; We&#8217;ve been busy on several Rails and Grails-based projects lately which is why we&#8217;re very excited about the releases of both Rails 2.0.x and the first full 1.0 release of the Grails framework.&nbsp;</p>
<p>The Grails release in particular is significant as the framework has finally emerged from &quot;in development&quot; status which removes one more barrier for web project teams and IT departments to using the framework.&nbsp; We&#8217;ve had success with the Grails framework particularly due to the fact that it sits very well in the Java enterprise ecosystem, including the relatively straightforward integration of existing Java-based Hibernate models.&nbsp; This integration with Hibernate, which is a key factor in Grails&#8217; ability to be a contender for new IT projects with teams that are Java EE and Spring/Hibernate-oriented, is a fairly straightorward process that involves dropping in your existing mapping XML and Java POJOs.&nbsp; As if by some magic, you get all the benefits of GORM on your existing Java POJO data model, including dynamic search methods and the criteria builder DSL.</p>
<ul>
<li>Groovy on Grails 1.0: <a href="http://grails.org/1.0+Release+Notes">http://grails.org/1.0+Release+Notes</a></li>
<li>Groovy/Grails Zone on DZone: <a href="http://groovy.dzone.com/">http://groovy.dzone.com/</a></li>
<li>Ruby on Rails 2.0: <a href="http://weblog.rubyonrails.org/2007/12/7/rails-2-0-it-s-done">http://weblog.rubyonrails.org/2007/12/7/rails-2-0-it-s-done</a></li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2008/02/07/happenings/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon EC2: 1st Impressions Mounting S3</title>
		<link>http://www.cantinaconsulting.com/2007/12/08/amazon-ec2-first-impressions-mounting-s3/</link>
		<comments>http://www.cantinaconsulting.com/2007/12/08/amazon-ec2-first-impressions-mounting-s3/#comments</comments>
		<pubDate>Fri, 07 Dec 2007 19:18:28 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Amazon Web Services]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/2007/12/08/amazon-ec2-first-impressions-mounting-s3/</guid>
		<description><![CDATA[We&#8217;ve got a small internal project at Cantina that aims to make use of the Groovy on Grails framework and some of our Grails plugins, and we plan on using S3 as the persistent storage for the project.&#160; We decided to test out a small EC2 instance at Amazon to use as an integration point [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve got a small internal project at Cantina that aims to make use of the Groovy on Grails framework and some of our <a href="/grails-plugins/">Grails plugins</a>, and we plan on using S3 as the persistent storage for the project.&nbsp; We decided to test out a small EC2 instance at Amazon to use as an integration point for the project for a couple reasons:</p>
<ul>
<li>EC2 instances are very quick to setup</li>
<li>They are not charged for data transfer to S3</li>
<li>They are presumably the closest you can be to your S3 storage in terms of network latency</li>
</ul>
<p>Setting up our initial EC2 instance was incredibly easy.&nbsp; There&#8217;s a wealth of pre-built Amazon Machine Images, or AMIs, out there with various configurations for different application servers, including Apache, MySQL, JBoss, Tomcat, and, our new favourite, Red5.&nbsp; I was able to get one up and running fairly quickly with the packages I needed (I love <a href="http://linux.duke.edu/projects/yum/">yum</a>).&nbsp;</p>
<p>Actually, I was floored by how fast I had a brand new server up and running, considering I&#8217;ve had requests submitted to fairly large enterprise grade hosting companies for such intensely complicated things as, say opening a new port in the firewall, take over a week.&nbsp; I guess the landscape is changing, but I digress&#8230;</p>
<p>In order to use Amazon S3 as the backing store for our new EC2 instance, we seemed to have a few options:</p>
<ol>
<li>Code our application to manage the transfer and synchronization of files to S3, perhaps via our <a href="/grails-plugins/amazon-s3-plugin/">Amazon S3 Grails Plugin</a></li>
<li>Utilize an S3-aware file synchronization tool such as the <a href="http://jets3t.s3.amazonaws.com/applications/applications.html#synchronize">jets3t Synchronize tool</a>, or the Ruby <a href="http://s3sync.net">s3sync</a> tool</li>
<li>Mount S3 as a filesystem in the EC2 instance</li>
</ol>
<p>Since we&#8217;ve already been doing #1, and #2 isn&#8217;t exactly real-time, we decided to give #3 a go.&nbsp; To do so, we enlisted the help of a couple of tools:</p>
<ul>
<li><a href="http://www.jungledisk.com">JungleDisk</a>: A multi-platform tool that provides a local WebDAV interface to S3, suitable for mounting as a filesystem from the Mac OS X Finder, or from Linux using&#8230;</li>
<li><a href="http://dav.sourceforge.net/">davfs2</a>: Linux filesystem driver that will mount a WebDAV URL to a mount point in the local filesystem</li>
</ul>
<p>JungleDisk is a great tool in general for interacting with an S3 account, and I&#8217;ve been using it for a little while now for my own backup purposes on my Mac development laptop.&nbsp; The Linux version provides a standalone command line program (in addition to the GUI that comes on all platforms) which can be run as a daemon and scripted to startup on boot.&nbsp;</p>
<p>The setup was surprisingly simple.&nbsp; To get JungleDisk running from the command line client, you need to provide a configuration file, commonly called jungledisk-settings.ini.&nbsp; The documentation says that you should run the GUI first to generate the file before running the command line version, but I was able to copy over the file from my Mac laptop and update the values for the EC2 instance.&nbsp; Here&#8217;s an example of the configuration file:</p>
<p><code>LoginUsername=<br />
LoginPassword=PROTECTED:<br />
AccessKeyID=XXXXXXXXXXXXXXXXXXXXX<br />
SecretKey=PROTECTED:XXXXXXXXXXXXXXXXXXXXX<br />
Bucket=default<br />
CacheDirectory=/var/cache/jungledisk<br />
ListenPort=2667<br />
CacheCheckInterval=120<br />
AsyncOperations=1<br />
Encrypt=0<br />
ProxyServer=<br />
EncryptionKey=PROTECTED:<br />
DecryptionKeys=PROTECTED:<br />
MaxCacheSize=1000<br />
MapDrive=<br />
UseSSL=0<br />
RetryCount=3<br />
FastCopy=1<br />
WebAccess=0<br />
LogDuration=30<br />
ArchiveFlag=5<br />
ArchiveDuration=60<br />
PasswordPrompt=0</code></p>
<p>I setup jungledisk to startup on boot using a really handy /etc/init.d script from the JungleDisk forums found <a href="http://forum.jungledisk.com/viewtopic.php?t=6337">here</a>.</p>
<p>Once JungleDisk was configured and running, I had a local WebDAV server running at http://localhost:2667.&nbsp; This could be used in the KDE to browse the filesystem, but since I&#8217;d like my web application to be able to access it via the filesystem, the next step was to get davfs2 running.</p>
<p>The EC2 instance did not have davfs2 installed by default (at least not the AMI I chose, which was based on the default AMI), so I simply downloaded the source distribution and compiled locally on the EC2 instance.&nbsp; The base AMI I was using did not have gcc or the neon development libraries (<a href="http://www.webdav.org/neon/">Neon</a> is a WebDAV library that davfs2 uses for communicating with WebDAV servers).&nbsp; Luckily yum was installed on the EC2 instance so getting these dependencies was pretty straightforward.</p>
<p>davfs2 can be configured to run by non-root users, or by root.&nbsp; The configuration of davfs2 depends on your choice here as some configuration options are intended only for system wide davfs2 configuration started from root.&nbsp; I opted to take this approach, setup my /usr/local/etc/davfs2.conf file with the following configuration options:</p>
<p><code> dav_user&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mydavuser<br />
dav_group&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mydavgroup<br />
kernel_fs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fuse<br />
ask_auth&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0</code></p>
<p>Since JungleDisk provides WebDAV access to localhost only, and does not require authentication, setting ask_auth to 0 is useful to prevent davfs2 from prompting for a password when mounting the WebDAV URL.&nbsp; Last but not least, I added an entry to /etc/fstab to configure the mount:</p>
<p><code>http://localhost:2667 /mountpoint davfs nolocks,noaskauth,rw</code></p>
<p>Voila!&nbsp; Now my S3 instance is mounted to the local Linux filesystem on my EC2 instance.&nbsp; I have not done any performance testing or cache tuning, but this <a href="http://info.rightscale.com/2007/11/29/network-performance-in-ec2-and-s3">article</a> over at Right Scale looks promising.&nbsp; Once we have our application and up and running, I&#8217;ll post back with some more information on how this configuration is working.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2007/12/08/amazon-ec2-first-impressions-mounting-s3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>One step closer to Grails 1.0</title>
		<link>http://www.cantinaconsulting.com/2007/12/04/one-step-closer-to-grails-10/</link>
		<comments>http://www.cantinaconsulting.com/2007/12/04/one-step-closer-to-grails-10/#comments</comments>
		<pubDate>Tue, 04 Dec 2007 15:18:22 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Groovy on Grails]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/2007/12/04/one-step-closer-to-grails-10/</guid>
		<description><![CDATA[Graeme and the Grails community have been hard at work lately getting Grails ready for a 1.0 release, and the latest release candidate, RC2 is quite indicative of their labors.&#160; There are some impressive additions to this release, including a initial pass at a full set of reference documentation, Spring 2.5, and over 140 bug [...]]]></description>
			<content:encoded><![CDATA[<p>Graeme and the Grails community have been hard at work lately getting Grails ready for a 1.0 release, and the latest release candidate, RC2 is quite indicative of their labors.&nbsp; There are some impressive additions to this release, including a initial pass at a full set of <a href="http://grails.org/doc/1.0.x/">reference documentation</a>, Spring 2.5, and over 140 <a href="http://jira.codehaus.org/browse/GRAILS?report=com.atlassian.jira.plugin.system.project:changelog-panel">bug fixes and improvements</a>.&nbsp; This is truly a herculean effort, and I can&#8217;t wait to start testing our plugins in RC2.&nbsp;</p>
<p>You can check get the latest and greatest, as always, at <a href="http://grails.org">grails.org.</a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2007/12/04/one-step-closer-to-grails-10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Red5 Plugin for Grails</title>
		<link>http://www.cantinaconsulting.com/2007/11/20/red5-plugin-for-grails/</link>
		<comments>http://www.cantinaconsulting.com/2007/11/20/red5-plugin-for-grails/#comments</comments>
		<pubDate>Mon, 19 Nov 2007 20:59:58 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Groovy on Grails]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/2007/11/20/red5-plugin-for-grails/</guid>
		<description><![CDATA[Continuing with my Grails plugin love fest,  I spent several 3-4 AM nights digging into how to integrate Red5 RTMP streaming into my Grails Video plugin.  The two options I came up with were:

Leave the Red5 functionality as a separate WAR and use a shared directory which the video plugin would deposit the [...]]]></description>
			<content:encoded><![CDATA[<p>Continuing with my Grails plugin love fest,  I spent several 3-4 AM nights digging into how to integrate Red5 RTMP streaming into my Grails Video plugin.  The two options I came up with were:</p>
<ol>
<li>Leave the Red5 functionality as a separate WAR and use a shared directory which the video plugin would deposit the encoded movies</li>
<li>Copy the war artifacts into the Grails plugin so the Grails app embeds the Red5 functionality within the WAR</li>
</ol>
<p>I opted for the latter because I would like to have the Red5 application code use GORM to read meta data about the Movie asset. Additionally, to have a tight integration with Spring Security I would like to have the artifacts share the same application context.  Finally, it is easier to debug code (btw, IntelliJ IDE rocks) if you don&#8217;t have to manage the startup of two different WARs. I&#8217;d like to say developing this plugin was easy, but in all honesty, it was a totally pain in the bum, and at the time, it seemed overly complex.  In hindsight though, I realize that the reason for the &ldquo;pain in the bum&rdquo; was my lack of understanding of the life cycle of the context loader in Spring.</p>
<p>Once that hurdle was jumped, due to the tight Java/J2EE integration, the rest of the plugin development, installation scripts, custom artifact, etc. was ridiculously easy. The work was mostly setting up Spring configuration for the plugin.  Because of how elegant the plugin architecture is, I think stitching together tiny pieces of functionality that is packaged in plugins is the best way to grow functionality base of Grails.</p>
<p>With this in mind I decided to release the Red5 integration work as a separate plugin and have the Video plugin depend on that for the RTMP streaming.  So if one person doesn&#8217;t want to use all the Video plugin functionality they can at least use the Red5 Integration functionality.  If you&#8217;d like to check it out  please find it in the grails plugins section of our site.  One thing to note is the Red5 plugin comes packaged with the source code for Red5.</p>
<p>I am going to send an email to the Red5 team and see if they will keep me abreast of new functionality as it comes down the road so I can maintain the plugin. I&#8217;ll keep folks posted on what they say.  Finally, I&#8217;d like to thank, the Red5 team for the their 0.6.3 WAR release of the Red5 server and Alexander zhukov who created Red5-minimal. The fact that Alexander was able to accomplish what he did let me know it was &ldquo;in theory&rdquo; possible to incorporate the functionality in a plugin and gave me inspiration during the dark times.  If you become the next youtube with this Grails plugin, throw a brother a couple bucks&#8230;. do the right thing <img src='http://www.cantinaconsulting.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2007/11/20/red5-plugin-for-grails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sweet Potato Pie!: A Video Plugin for Groovy on Grails</title>
		<link>http://www.cantinaconsulting.com/2007/11/10/sweet-potato-pie-a-video-plugin-for-groovy-on-grails/</link>
		<comments>http://www.cantinaconsulting.com/2007/11/10/sweet-potato-pie-a-video-plugin-for-groovy-on-grails/#comments</comments>
		<pubDate>Fri, 09 Nov 2007 20:49:55 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Groovy on Grails]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/2007/11/10/sweet-potato-pie-a-video-plugin-for-groovy-on-grails/</guid>
		<description><![CDATA[Hi All,  adding to the new found obsession we have for Groovy on Grails, we ripped out a Video Plugin to convert and display flash videos. Hopefully it will give folks something fun to play with on the weekend  
You can find information about the plugin on our Grails Video Plugin Page.
And as [...]]]></description>
			<content:encoded><![CDATA[<p>Hi All,  adding to the new found obsession we have for Groovy on Grails, we ripped out a Video Plugin to convert and display flash videos. Hopefully it will give folks something fun to play with on the weekend <img src='http://www.cantinaconsulting.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>You can find information about the plugin on our <a href="http://www.cantinaconsulting.com/grails-plugins/video-plugin/"><font color="#bb6f02">Grails Video Plugin Page</font></a>.</p>
<p>And as with the Amazon S3 Plugin, this is a very preliminary version, and we&rsquo;re hoping to get some good feedback from the <a target="_blank" href="http://grails.codehaus.org/Mailing+lists"><font color="#bb6f02">Grails Community</font></a> and you on what we can do better.  However, there may be some bugs that we haven&rsquo;t quite gotten to yet.</p>
<p>Feel free to leave comments regarding the plugin on this posting.  We know we have a lot more testing to do and features to add, so any feedback is most welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2007/11/10/sweet-potato-pie-a-video-plugin-for-groovy-on-grails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hot Off The Press: An Amazon S3 Plugin for Groovy on Grails</title>
		<link>http://www.cantinaconsulting.com/2007/11/06/hot-off-the-press-an-amazon-s3-plugin-for-groovy-on-grails/</link>
		<comments>http://www.cantinaconsulting.com/2007/11/06/hot-off-the-press-an-amazon-s3-plugin-for-groovy-on-grails/#comments</comments>
		<pubDate>Mon, 05 Nov 2007 18:22:44 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Amazon Web Services]]></category>
		<category><![CDATA[Groovy on Grails]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/2007/11/06/hot-off-the-press-an-amazon-s3-plugin-for-groovy-on-grails/</guid>
		<description><![CDATA[We&#8217;ve released our first ever plugin for the Groovy on Grails web application framework!&#160; You can see the details over on our new Grails Plugins page.&#160;
In short, we wanted to build something that would manage static file assets such as images, movies, audio, Flash, and perhaps down the road, site backups, on the Amazon Simple [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve released our first ever plugin for the Groovy on Grails web application framework!&nbsp; You can see the details over on our new <a href="http://www.cantinaconsulting.com/grails-plugins/">Grails Plugins</a> page.&nbsp;</p>
<p>In short, we wanted to build something that would manage static file assets such as images, movies, audio, Flash, and perhaps down the road, site backups, on the Amazon Simple Storage Service (S3).&nbsp;</p>
<p>This is a very preliminary version of the plugin, and we&#8217;re hoping to get some good feedback from the <a href="http://grails.codehaus.org/Mailing+lists" target="_blank">Grails Community</a> and you on what we can do better.&nbsp; However, there may be some bugs that we haven&#8217;t quite gotten to yet.&nbsp;</p>
<p>Feel free to leave comments regarding the plugin on this posting.&nbsp; We know we have a lot more testing to do and features to add, so any feedback is most welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2007/11/06/hot-off-the-press-an-amazon-s3-plugin-for-groovy-on-grails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Red5 wicked cool</title>
		<link>http://www.cantinaconsulting.com/2007/10/31/red5-wicked-cool/</link>
		<comments>http://www.cantinaconsulting.com/2007/10/31/red5-wicked-cool/#comments</comments>
		<pubDate>Wed, 31 Oct 2007 16:37:04 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[RIA / Flash]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=16</guid>
		<description><![CDATA[I have been playing around with Red5 Media Server, the open source flash server. I have to say &#8211; wicked cool. I&#8217;d never be able to afford a working version of Flash Media Server but always wanted to play around with the functionality.
I&#8217;m amazed at the way the Red5 developers have been able to reverse [...]]]></description>
			<content:encoded><![CDATA[<p>I have been playing around with Red5 Media Server, the open source flash server. I have to say &#8211; wicked cool. I&#8217;d never be able to afford a working version of Flash Media Server but always wanted to play around with the functionality.</p>
<p>I&#8217;m amazed at the way the Red5 developers have been able to reverse engineer the protocol for the RTMP by observing byte streams &#8211; who wooda thunk.  Check it out at &#8211; <a href="http://osflash.org/red5/discovery ">http://osflash.org/red5/discovery </a>   or check out this email discussion thread &#8211; <a href="http://osflash.org/pipermail/red5_osflash.org/2005-September/000134.html">http://osflash.org/pipermail/red5_osflash.org/2005-September/000134.html</a></p>
<p>Anyway, for anyone unfamiliar with the Red5 technology the server is built in Java (Ruby version to come soon???) and the install was fairly easy. You can install both as a standalone server (Mac OSX) and deployed as Tomcat app (series of  WARs).  The standalone version uses Tomcat under the covers.</p>
<p>The demo flash apps included in the install were:</p>
<p>An app acting as as video broadcaster<br />
An app that records a video stream to the server using flash<br />
An app that is a chat room<br />
An app that uses Shared Objects<br />
A couple others&#8230;</p>
<p>They all worked fairly well, however, I ran into two problems. The first problem was  not related to Red5 but  that Flash did not recognize the video drivers (using an Intel MacBook Pro) and I had to change the preferences for Flash movies to use the USB Video Class.</p>
<p>The second problem was that the video quality was a little rough for the video recorder. Still working on the issue, please leave a comment if you have any ideas.</p>
<p>Finally, I found a great video tutorial site that covers some basics to setting up the Red5 server. It also, helped me setup a free development environment for Flash movies. Check it out &#8211; <a href="http://www.flashextensions.com/tutorials.php">http://www.flashextensions.com/tutorials.php</a></p>
<p>Some of the videos are really basic and geared towards actionscript developers &#8211; i.e., setting up Eclipse &#8211; but I found some of the others pretty useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2007/10/31/red5-wicked-cool/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How Healthy is Grails?</title>
		<link>http://www.cantinaconsulting.com/2007/10/29/how-healthy-is-grails/</link>
		<comments>http://www.cantinaconsulting.com/2007/10/29/how-healthy-is-grails/#comments</comments>
		<pubDate>Mon, 29 Oct 2007 16:22:35 +0000</pubDate>
		<dc:creator>matt</dc:creator>
				<category><![CDATA[Groovy on Grails]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=15</guid>
		<description><![CDATA[One question we get a lot at Cantina is that of whether Grails is a passing fad, or if it is something that has some staying power. We have gotten that question (in some form or another) quite a bit, so it might help to explain where we&#8217;re coming from.
I agree with Adam&#8217;s thoughts in [...]]]></description>
			<content:encoded><![CDATA[<p>One question we get a lot at Cantina is that of whether Grails is a passing fad, or if it is something that has some staying power. We have gotten that question (in some form or another) quite a bit, so it might help to explain where we&#8217;re coming from.</p>
<p>I agree with Adam&#8217;s thoughts in his previous post and have been very impressed with the activity in the Grails community. I subscribed to the user mailing list. Each day I receive from this list anywhere from 40-60 emails from users running into various issues on projects and folks from the Grails community providing their suggestions or troubleshooting tips.   The activity of user/developer mailing lists is one of the most important benchmarks in determining the health of an open source framework &#8211; along with supplied functionality (obvious), core technology, the architects driving the vision, commercial support, documentation, check-in velocity and discussion in the blogosphere. To give an indication of the acceleration of activity in the Grails community, in October 2006 the same mailing list was averaging around 5-6 emails &#8211; almost a 10 fold increase in one year.***</p>
<p>Also, last week on the Grails user mailing list, there was some spirited debate on the level of Grails documentation (or lack of it) and whether it was appropriate for the release level of the framework.  The amount of documentation right now doesn&#8217;t really concern me. What struck me the most about the dialog was the intensity of the debate. It shows the community is excited about what has been developed, are passionate to help out in whatever way they can, and care deeply about the frameworks success.  And the community&#8217;s passion/enthusiasm for Groovy/Grails is clearly indicative of the framework&#8217;s ability to meet a need and fill a gap, something the community is looking for.  IMHO this enthusiasm will be the driving force of success and perpetuate Grail&#8217;s momentum.  And while more formal documentation is sure to come down the road, I&#8217;ve found the answer to most of the issues i&#8217;ve run into by querying the mailing list. It has been an excellent source of living documentation.  &#8211; <a href="http://www.nabble.com/codehaus---grails-f11860.html">http://www.nabble.com/codehaus&#8212;grails-f11860.html</a></p>
<p>Of course with every new open source project there is always a lot of user/developer mailing list activity in the beginning. The question always becomes: Does this activity last, does it have staying power?  With over a year and half of Grails development under their belt, a pending 1.0 release, and the clear need for a rapid application development framework in the J2EE architecture landscape, I have the feeling Grails is here to stay.  Now I&#8217;m just trying to find the best way to support the growth&#8230; <img src='http://www.cantinaconsulting.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>That being said, one of our goals here at Cantina will be to leave some tips/issues that we run into as we develop plugins for the framework.  Although it will not be formal documentation &#8211; we get our kicks from developing functionality &#8211;  there may be some issue/tips that we run into that can be helpful to you. And please feel free to weigh in by leaving a comment if you know a better approach.</p>
<p>*** fyi, this calculation was performed with a VERY informal last year inspection of the mailing list on Nabble</p>
<p>UPDATE &#8211; 10/31/2007</p>
<p>I guess I should be been paying attention to the email threads a little better&#8230; <img src='http://www.cantinaconsulting.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Two email threads -</p>
<p><a href="http://www.nabble.com/number-of-people-companies-using-Grails-tf4721318.html">http://www.nabble.com/number-of-people-companies-using-Grails-tf4721318.html</a></p>
<p>and</p>
<p><a href="http://www.nabble.com/Mailing-lists-statistics-tf4693805.html#a13416495">http://www.nabble.com/Mailing-lists-statistics-tf4693805.html#a13416495</a></p>
<p>also discuss the growing activity of the mailing list.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2007/10/29/how-healthy-is-grails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What I like about Groovy on Grails</title>
		<link>http://www.cantinaconsulting.com/2007/10/26/what-i-like-about-groovy-on-grails/</link>
		<comments>http://www.cantinaconsulting.com/2007/10/26/what-i-like-about-groovy-on-grails/#comments</comments>
		<pubDate>Fri, 26 Oct 2007 16:35:51 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Groovy on Grails]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=14</guid>
		<description><![CDATA[First let me congratulate all the folks that have been going crazy getting the Groovy on Grails (grails.org) framework to version 1.0 (almost there!).  Just when I think my 0.5.6 version is going to be around for a while, they start releasing more versions, with a fury.
We&#8217;ve used Java here at Cantina on innumerable [...]]]></description>
			<content:encoded><![CDATA[<p>First let me congratulate all the folks that have been going crazy getting the Groovy on Grails (<a href="http://grails.org" target="_blank">grails.org</a>) framework to version 1.0 (almost there!).  Just when I think my 0.5.6 version is going to be around for a while, they start releasing more versions, with a fury.</p>
<p>We&#8217;ve used Java here at Cantina on innumerable projects with a great deal of success.  The toolset is very complete and Spring and Hibernate have been a godsend for allowing us to focus on the intellectual &quot;meat&quot; of a project.  Then, in an effort to explore some new technology for a couple prototypes we were working on we found Grails.</p>
<p>I think the first thing that drew us (me) to Grails was the mantra that I heard over and over again at a talk given by Venkat Subramaniam at Sun a while ago regarding Groovy on Grails have more &quot;signal to noise&quot;.  Less syntactical noise, more  code signal (i.e., the &quot;meat&quot;).  In his talk he threw together an AJAX enabled form in about 10-15 minutes with all the CRUD and validation you need.</p>
<p>Once we started using Grails in house, it quickly became apparent how deep the mantra of having a greater &quot;signal to noise&quot; went.  We love Spring and Hibernate but we hate XML configuration.  Yes, XML is ubiquitous, very readable, and supported everywhere, but, as technologies like Spring and Hibernate put more of our application structure into XML, it makes it very hard to <em>debug</em> all of our application when some of the structure sits in very static XML.</p>
<p>Grails provides a great approach to this.  Through the Grails BeanBuilder, you specify all of that lovely Spring configuration within a very readable and debuggable Groovy syntax.  This makes for a much more powerful way to configure the structure of your application as well as allows you to actually step through parts of your configuration with a debugger.</p>
<p>Of course, Grails does a whole lot more than that (including a lot of the auto-wiring in Spring so that you  don&#8217;t have to do <em>any</em> configuration), and here are just some of the things that caught our eye:</p>
<ul>
<li>GORM (Grails Object Relational Mapper): as if Hibernate wasn&#8217;t powerful enough, Grails adds some useful methods of querying and mapping your object model that go above and beyond Hibernate.  With dynamic methods, you can query against properties of your object model classes (domain classes) via methods that you never have to write, like this:<br />
    <span class="Code"><br />
    // Assuming you have a domain class called &quot;Person&quot; <br />
    // with a name property and a type property that </span><span class="Code"><br />
    // can be &quot;employee&quot; or &quot;customer&quot;&nbsp;&nbsp; </p>
<p>    def allPeople = Person.findAll()&nbsp; <br />
    def onlyEmployees = Person.findByType(&quot;employee&quot;)&nbsp; <br />
    def howManyEmployees = Person.countByType(&quot;employee&quot;)</span></p>
<p>    I didn&#8217;t have to write any of these find* or count* methods, they come free of charge with GORM which makes the simple queries a lot easier to manage.</li>
<li>Auto-reloading: one thing that has always plagued us as Java developers is the development cycle of fix -&gt; deploy -&gt; start -&gt; test.  There are certainly ways to reduce this cycle in Java, but sometimes the project just doesn&#8217;t allow for it.  Grails is built with the mindset that changes to most code assets should be reflected instantly in the running application, thus reducing the time it takes to test code changes</li>
<li>TagLibs: Creating GSP (analogous to JSP) tag libraries requires much less code and no configuration to get your tags and and running</li>
<li>Intellij IDEA Integration: I love <a href="http://www.macromates.com">TextMate</a> as much as the next guy, but code completion and debugging are things I&#8217;ve just gotten too used to (call me lazy).  The Groovy/Grails plugin for Intellij IDEA has come a long way towards making Grails a first class IDE citizen.</li>
<li>Legacy Integration:  A lot of the projects we work on involves an existing Java application and SQL database.  There is often business logic already implemented in Java classes (Spring or otherwise) that really don&#8217;t need to be rewritten.  Since, at the end of the day, Grails is Java, we can make use of the existing codebase in a way that is much more seamless than if we were to introduce another web technology.  Also, the fact that it&#8217;s all Hibernate under the hood makes it easier to adapt a set of domain classes to an existing database schema.  This makes Grails an easier sell on those technical re-architecture projects in the Java world.</li>
</ul>
<p>Beyond the technology, there&#8217;s just a lot of momentum in the Grails community.  Within the last year that I&#8217;ve been watching, Grails has gone from a 0.4 to just about 1.0 (I&#8217;ve been using PHP frameworks that haven&#8217;t bumped the minor version number in over 2 years).  There&#8217;s a healthy and growing list of plugins (<a href="http://grails.org/Plugins">grails.org/Plugins</a>) that seem to be addressing the core needs of new application development.&nbsp; We&#8217;re really looking forward to the next Grails project and experiencing a lot more signal and a lot less noise.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2007/10/26/what-i-like-about-groovy-on-grails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Benvenuto!</title>
		<link>http://www.cantinaconsulting.com/2007/10/19/benvenuto/</link>
		<comments>http://www.cantinaconsulting.com/2007/10/19/benvenuto/#comments</comments>
		<pubDate>Thu, 18 Oct 2007 19:57:16 +0000</pubDate>
		<dc:creator>adam</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.cantinaconsulting.com/?p=6</guid>
		<description><![CDATA[Greetings and salutations to all, and welcome to the very first blog post at Cantina.
First things are always first, and in the spirit of blogging as a new form of journalism (not http://en.wikipedia.org/wiki/New_Journalism) let&#8217;s get the main questions that any reporter would ask out of the way:
Who
We&#8217;re a new boutique internet technology shop specializing in [...]]]></description>
			<content:encoded><![CDATA[<p>Greetings and salutations to all, and welcome to the very first blog post at Cantina.</p>
<p>First things are always first, and in the spirit of blogging as a new form of journalism (not <a title="New Journalism" target="_blank" href="http://en.wikipedia.org/wiki/New_Journalism">http://en.wikipedia.org/wiki/New_Journalism</a>) let&#8217;s get the main questions that any reporter would ask out of the way:</p>
<p><strong>Who</strong></p>
<p>We&#8217;re a new boutique internet technology shop specializing in whatever it takes to effectively produce web things (see About section).</p>
<p><strong>What</strong></p>
<p>What do we do?  Well, sometimes it involes banging our heads against the wall, but at the end of the day we make great web sites and applications using best of breed practices and technologies (yes, you can read Web 2.0 in there).</p>
<p><strong>When</strong></p>
<p>We&#8217;ve been doing this for over 15+ years combined, but the blog starts today.</p>
<p><strong>Why</strong></p>
<p>We often ask ourselves that same question, but in the end, we love what we do!</p>
<p><strong>How</strong></p>
<p>Using some of these: agile methodologies, iterative design and development, rapid development frameworks and lots of testing.</p>
<p>In the process of doing what we do, we end up figuring some things out, and as part of the open source credo of &#8220;share what you know&#8221; (which sometimes comes in the form of &#8220;patch it if it&#8217;s broken&#8221;), we decided to start blogging about our little victories against buggy code.  We hope that you find at least something that we&#8217;ve written here useful, and who knows, maybe someday we can do business together.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cantinaconsulting.com/2007/10/19/benvenuto/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
