<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Matt Stine&#039;s Blog &#187; CodeProject</title>
	<atom:link href="http://mattstine.com/category/codeproject/feed/" rel="self" type="application/rss+xml" />
	<link>http://mattstine.com</link>
	<description>Thoughts on Java, Groovy, Grails, Agile Development, etc. etc. etc.</description>
	<lastBuildDate>Tue, 17 May 2011 17:02:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='mattstine.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Matt Stine&#039;s Blog &#187; CodeProject</title>
		<link>http://mattstine.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://mattstine.com/osd.xml" title="Matt Stine&#039;s Blog" />
	<atom:link rel='hub' href='http://mattstine.com/?pushpress=hub'/>
		<item>
		<title>I&#8217;ve &#8220;forked&#8221; the Grails PayPal Plugin&#8230;</title>
		<link>http://mattstine.com/2009/05/02/ive-forked-the-grails-paypal-plugin/</link>
		<comments>http://mattstine.com/2009/05/02/ive-forked-the-grails-paypal-plugin/#comments</comments>
		<pubDate>Sat, 02 May 2009 05:59:46 +0000</pubDate>
		<dc:creator>mattstine</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[grails]]></category>
		<category><![CDATA[groovy]]></category>

		<guid isPermaLink="false">http://www.mattstine.com/?p=158</guid>
		<description><![CDATA[I&#8217;m currently completing the finishing touches on a new e-commerce site for my wife&#8217;s stationary business. We decided a long time ago to use PayPal for all of the payment processing since we&#8217;ve had a great experience using it for our eBay selling. About a year ago Graeme Rocher polished off the last release of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=158&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently completing the finishing touches on a new e-commerce site for my wife&#8217;s stationary business. We decided a long time ago to use <a href="http://www.paypal.com">PayPal</a> for all of the payment processing since we&#8217;ve had a great experience using it for our eBay selling. About a year ago Graeme Rocher polished off the last release of a <a href="http://grails.org/plugin/paypal">PayPal plugin</a> that is available in <a href="http://grails.org/plugin/home">the Grails Plugin repository</a>. It really is a very nice plugin, yet I had a couple of problems with it:</p>
<ul>
<li>It is only capable of handling payments for one item transactions via &#8220;Buy Now&#8221; buttons. I want to upload an entire shopping cart full of multiple items.</li>
<li>It currently won&#8217;t handle shipping addresses. The site I&#8217;m building allows the user to maintain a list of shipping addresses, and I&#8217;d want to send the address information they choose along to PayPal.</li>
<li>Minor issue: needed to upgrade the plugin to Grails 1.1.</li>
</ul>
<p>So, I decided this evening to fork the plugin. I want to leverage all of the great work that has been done thus far (especially with the IPN processing part &#8211; superb stuff), but I have to add in these two functions and do the version upgrade. Interestingly enough I couldn&#8217;t get the tests to run out of the box after the upgrade. No good developer likes to modify code without a stable running test suite, right? So what I ended up doing was creating a new Grails 1.1 plugin project and copying the original artifacts over. Once this was done all of the tests ran perfectly.</p>
<p>So, at this point I&#8217;ve added function #1. You can now redirect to the &#8220;uploadCart&#8221; action. It assumes that you have already constructed a Payment object (now containing PaymentItems) and saved it, and then passed the transactionId along. I did this so that folks with multiple different ways of handling shopping carts could have some degree of flexibility &#8211; the onus is on you to map your cart to your Payment object correctly. The original functions implemented by Graeme are backward compatible, assuming only one PaymentItem in the Payment. I&#8217;ve run all of the original tests and also did some manual functional testing by running the plugin app against my own PayPal Sandbox account. So far so good. Look for more updates as this evolves. Once I get something I&#8217;m totally happy with I&#8217;ll see about getting it pushed back into the main plugin repo.</p>
<p>Want to take a closer look? Visit <a href="http://github.com/mstine/grails-paypal-plugin/tree/master">http://github.com/mstine/grails-paypal-plugin/tree/master</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mattstine.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mattstine.wordpress.com/158/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mattstine.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mattstine.wordpress.com/158/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mattstine.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mattstine.wordpress.com/158/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mattstine.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mattstine.wordpress.com/158/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mattstine.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mattstine.wordpress.com/158/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mattstine.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mattstine.wordpress.com/158/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mattstine.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mattstine.wordpress.com/158/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=158&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mattstine.com/2009/05/02/ive-forked-the-grails-paypal-plugin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1eaa45fee6a2b0c4b479b2982a4274f4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mattstine</media:title>
		</media:content>
	</item>
		<item>
		<title>Groovy: Post to a URL</title>
		<link>http://mattstine.com/2009/04/25/groovy-post-to-a-url/</link>
		<comments>http://mattstine.com/2009/04/25/groovy-post-to-a-url/#comments</comments>
		<pubDate>Sun, 26 Apr 2009 04:09:11 +0000</pubDate>
		<dc:creator>mattstine</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[groovy]]></category>

		<guid isPermaLink="false">http://www.mattstine.com/?p=146</guid>
		<description><![CDATA[If you&#8217;ve ever worked with the brilliant Recaptcha service, you&#8217;ll know that their REST API requires an HTTP POST rather than a GET. As I had only used GET requests thus far, I googled around and found a pretty easy solution: private def evaluateCaptcha(def remoteIp, def challenge, def response) { def config = recaptchaService.getRecaptchaConfig() def [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=146&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever worked with the brilliant <a href="http://recaptcha.net/">Recaptcha</a> service, you&#8217;ll know that their REST API requires an HTTP POST rather than a GET. As I had only used GET requests thus far, I googled around and found a pretty easy solution:</p>
<pre class="brush: groovy">
private def evaluateCaptcha(def remoteIp, def challenge, def response) {
    def config = recaptchaService.getRecaptchaConfig()

    def urlString = "http://api-verify.recaptcha.net/verify"
    def queryString = "privatekey=${config.recaptcha.privateKey}&amp;remoteip=${remoteIp}&amp;challenge=${challenge}&amp;response=${URLEncoder.encode(response)}"

    def url = new URL(urlString)
    def connection = url.openConnection()
    connection.setRequestMethod("POST")
    connection.doOutput = true

    def writer = new OutputStreamWriter(connection.outputStream)
    writer.write(queryString)
    writer.flush()
    writer.close()
    connection.connect()

    def recaptchaResponse = connection.content.text
    log.debug(recaptchaResponse)

    recaptchaResponse.startsWith("true")
}
</pre>
<p>I have to credit <a href="http://www.fiascode.com/programming/putting-google-finance-to-rest-with-groovy/">Justin Spradlin</a> for the code that ultimately got me here. Consider this a +1.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mattstine.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mattstine.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mattstine.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mattstine.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mattstine.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mattstine.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mattstine.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mattstine.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mattstine.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mattstine.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mattstine.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mattstine.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mattstine.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mattstine.wordpress.com/146/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=146&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mattstine.com/2009/04/25/groovy-post-to-a-url/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1eaa45fee6a2b0c4b479b2982a4274f4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mattstine</media:title>
		</media:content>
	</item>
		<item>
		<title>Grails, Prototype, Script.aculo.us &#8211; Persistent Grid Sorting Goodness</title>
		<link>http://mattstine.com/2009/04/25/grails-prototype-scriptaculous-persistent-grid-sorting-goodness/</link>
		<comments>http://mattstine.com/2009/04/25/grails-prototype-scriptaculous-persistent-grid-sorting-goodness/#comments</comments>
		<pubDate>Sat, 25 Apr 2009 05:14:40 +0000</pubDate>
		<dc:creator>mattstine</dc:creator>
				<category><![CDATA[ajax]]></category>
		<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[grails]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[prototype]]></category>
		<category><![CDATA[scriptaculous]]></category>

		<guid isPermaLink="false">http://www.mattstine.com/?p=139</guid>
		<description><![CDATA[Ever wanted to do drag-n-drop sorting of a grid of images on a page and persist it? Here&#8217;s my solution using Grails, Prototype, and Script.aculo.us. Basically what prompted this was the need for my wife to be able to sort the various product images that she had on a screen at any given time in [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=139&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Ever wanted to do drag-n-drop sorting of a grid of images on a page and persist it? Here&#8217;s my solution using Grails, Prototype, and Script.aculo.us.</p>
<p>Basically what prompted this was the need for my wife to be able to sort the various product images that she had on a screen at any given time in any way that she pleased, and it had to be easy to work with. What follows is by no means a complete solution to this problem, but it represents where I am in the development process and may be useful to you, my hapless reader.</p>
<p>Here&#8217;s some GSP code which basically lays out a grid of product images, 3 wide by <em>n</em> deep:</p>
<pre class="brush: xml">
&lt;div id="productThumbContainer"&gt;
  &lt;g:set var="rowIndex" value="${0}"/&gt;
&lt;g:each in="${products}" var="product" status="index"&gt;
  &lt;g:if test="${index % 3 == 0}"&gt;
    &lt;div id="productRow${rowIndex}" class="span-20 last product-row"&gt;
  &lt;/g:if&gt;
  &lt;div id="product_${product.id}" class="span-6 product &lt;g:if test="${(index % 3 == 2) || ((products.size() - index) == 1)}"&gt;last&lt;/g:if&gt;&lt;g:else&gt;append-1&lt;/g:else&gt;"&gt;
    &lt;img src="${resource(dir: grailsApplication.config.store.productImages.webPath, file: product?.thumbnailImage?.name)}" width="230" class="productImage"&gt;
    &lt;h3&gt;&lt;g:link controller="product" action="show" id="${product.id}"&gt;${product.name}&lt;/g:link&gt;&lt;/h3&gt;
  &lt;/div&gt;
  &lt;g:if test="${(index % 3 == 2) || ((products.size() - index) == 1)}"&gt;
    &lt;/div&gt;
    &lt;g:set var="rowIndex" value="${rowIndex + 1}"/&gt;
  &lt;/g:if&gt;
&lt;/g:each&gt;
&lt;/div&gt;
</pre>
<p>Now here&#8217;s where the magic happens:</p>
<pre class="brush: js">
document.observe('dom:loaded', function() {
      var productRows = $$('.product-row');

      var options = {
        constraint: false,
        overlap: 'horizontal',
        containment: productRows,
        dropOnEmpty: true,
        tag: 'div',
        onUpdate: updateRows
      };

      productRows.each(function(item) {
        Sortable.create(item, options);
      });

      $('persistOrderingButton').observe('click', function(event) {
          var sortString = '';
          productRows.each(function(row) {
              sortString += '&amp;';
              sortString += Sortable.serialize(row);
          });
          &lt;g:remoteFunction action="sortProducts" params="sortString" update="ajaxMessage" onSuccess="\$('ajaxMessage').show()"/&gt;
      });
});
</pre>
<p>What we&#8217;ve got here is, failure to communicate&#8230;oops, wrong synapse there&#8230;what we&#8217;ve got here is a Prototype selector that grabs everything with the class &#8220;.product-row.&#8221; It then takes these and creates a Scriptaculous Sortable for each of them, providing the object-literal &#8220;options.&#8221; Notice the &#8220;containment&#8221; option which allows you to drag products back and forth between the various rows.</p>
<p>Delving deeper into the magic is the callback function &#8220;updateRows.&#8221; This guy is my favorite Javascript creation in quite some time:</p>
<pre class="brush: js">
function updateRows(list) {
      var children = list.childElements();

      if (children.size() &lt; 3) {

        //If I&#039;m the last row, who cares!
        if (list.next() != null) {
          var prevRow = list.previous();

          if (prevRow != null) {
            var lastChild = prevRow.childElements()[prevRow.childElements().size() - 1].remove();
            list.insert({top:lastChild});
            updateRows(prevRow);
          } else {
            var lastRow = list.up().childElements()[list.up().childElements().size() - 1];
            var lastChild = lastRow.childElements()[lastRow.childElements().size() - 1].remove();
            list.insert({top:lastChild});
            updateRows(lastRow);
          }
        }
      } else if (children.size() == 3) {
        //Do nothing...gets me out of the recursion I hope!
      } else {
        var nextRow = list.next();
        var lastChild = children[children.size() - 1].remove();

        if (nextRow != null) {
          nextRow.insert({top:lastChild});
          updateRows(nextRow);
        } else {
          var topRow = list.up().childElements()[0];
          topRow.insert({top:lastChild});
          updateRows(topRow);
        }
      }

      var i = 0;
      Sortable.sequence(list).each(function(item) {
        var productId = &#039;product_&#039; + item;
        if (i &lt; 2) {
          $(productId).removeClassName(&#039;last&#039;);
          $(productId).removeClassName(&#039;append-1&#039;);
          $(productId).addClassName(&#039;append-1&#039;);
        } else {
          $(productId).removeClassName(&#039;last&#039;);
          $(productId).removeClassName(&#039;append-1&#039;);
          $(productId).addClassName(&#039;last&#039;);
        }
        i++;
      });
}
</pre>
<p>This function is organized around the fact that the only valid state for a grid of n-rows will be n-1 rows of 3 products, followed by one row of 1 &lt;= numProducts &lt;= 3. In most cases, if you drag a product from one row to another, you are violating that rule by creating a row with 2 products and a row with 4 products. This function solves the problem by recursively shifting the products down until reaching a stable state again.</p>
<p>There&#039;s a bit of noise there at the bottom of the function. I&#039;m using Blueprint CSS to do the layout for this application and I need to shift the various Blueprint classes around once everything is settled.</p>
<p>Finally, here&#039;s the persistence of the data when we click save:</p>
<pre class="brush: groovy">
def sortProducts = {
    TreeMap rowMap = new TreeMap()

    params.each {key, value -&gt;
      def matcher = key =~ /productRow(.*)\[\]/
      if (matcher.matches()) {
        def rowId = matcher[0][1]
        rowMap[rowId] = value
      }
    }

    def productIds = []
    rowMap.values().each { row -&gt;
      row.each {
        productIds &lt;&lt; it.toLong()
      }
    }

    shoppingService.saveSortOrder(productIds)

    render(&quot;Product sort order saved!&quot;)
}
</pre>
<p>and the logic from shoppingService.saveSortOrder():</p>
<pre class="brush: groovy">
def saveSortOrder(def productIds) {
    def productsToSort = Product.findAllByIdInList(productIds)

    def productMap = [:]
    def sortIndexList = []

    productsToSort.each {
      productMap[it.id] = it
      sortIndexList &lt;&lt; it.sortIndex
    }

    sortIndexList.sort()
    sortIndexList = sortIndexList.reverse()

    productIds.each {
      productMap[it].sortIndex = sortIndexList.pop()
    }

    productsToSort.each {
      it.save()
    }
}
</pre>
<p>You might wonder why this is so complex. What I haven&#8217;t fully described is the way products are organized into a hierarchy of various categories. When you&#8217;re sorting a screen, you&#8217;re only sorting a subset of the products that are in that particular category. However, the sort order is maintained across the entire product set in the database. So, this logic basically just shifts around the existing sort indicies, placing them in their new relative order.</p>
<p>Anyway, I don&#8217;t know how generally applicable this code is, but I had fun writing it and I hope you can get some use out of it. Cheers!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mattstine.wordpress.com/139/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mattstine.wordpress.com/139/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mattstine.wordpress.com/139/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mattstine.wordpress.com/139/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mattstine.wordpress.com/139/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mattstine.wordpress.com/139/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mattstine.wordpress.com/139/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mattstine.wordpress.com/139/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mattstine.wordpress.com/139/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mattstine.wordpress.com/139/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mattstine.wordpress.com/139/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mattstine.wordpress.com/139/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mattstine.wordpress.com/139/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mattstine.wordpress.com/139/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=139&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mattstine.com/2009/04/25/grails-prototype-scriptaculous-persistent-grid-sorting-goodness/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1eaa45fee6a2b0c4b479b2982a4274f4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mattstine</media:title>
		</media:content>
	</item>
		<item>
		<title>LOTY&#8230;Part Deux</title>
		<link>http://mattstine.com/2009/04/06/lotypart-deux/</link>
		<comments>http://mattstine.com/2009/04/06/lotypart-deux/#comments</comments>
		<pubDate>Tue, 07 Apr 2009 03:31:58 +0000</pubDate>
		<dc:creator>mattstine</dc:creator>
				<category><![CDATA[agile]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[dynamiclanguages]]></category>
		<category><![CDATA[goals]]></category>
		<category><![CDATA[loty]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://www.mattstine.com/?p=117</guid>
		<description><![CDATA[A few days ago I pontificated on my need to choose a new &#8220;Language of the Year.&#8221; Right now I&#8217;m attempting to choose between Scala and Clojure. If nothing else, I&#8217;ve learned from this exercise that asking the community for feedback is a GOOD thing. Your comments have been very helpful. To summarize: As far [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=117&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-120" title="scala_vs_clojure" src="http://mattstine.files.wordpress.com/2009/04/scala_vs_clojure.jpg?w=570" alt="scala_vs_clojure"   style="float:left;margin-right:20px;" /><a href="http://mattstine.files.wordpress.com/2009/04/scala_vs_clojure.jpg2009/04/02/loty-time-again-scala-or-clojure">A few days ago I pontificated</a> on my need to choose a new &#8220;Language of the Year.&#8221; Right now I&#8217;m attempting to choose between <a href="http://www.scala-lang.org/">Scala</a> and <a href="http://clojure.org/">Clojure</a>. If nothing else, I&#8217;ve learned from this exercise that asking the community for feedback is a GOOD thing. Your comments have been very helpful.</p>
<p>To summarize:</p>
<ol>
<li>As far as the polls go, Scala is in the lead by a margin of 4 to 2.</li>
<li>Two of the Scala votes have been simple +1&#8242;s, and two have provided a supporting argument.</li>
<li>Both Clojure voters have provided a supporting argument.</li>
<li>So, to make this a bit more of a fair fight, I&#8217;m only going to consider the &#8220;supported votes&#8221; at this point. This leads to the obvious result of a tie!</li>
</ol>
<p>So, what to do?</p>
<p>The argument for using Scala is that it is a functional/OO hybrid, so it will be easier to slide into. Interestingly enough, the argument against using Scala is that it is a functional/OO hybrid, so it will be easier to slide back into OO/imperative habits! Clojure, being more of a purely functional language, will be harder to get into initially, but will force me to think functionally. Hmmm&#8230;</p>
<p>So here&#8217;s my idea. Let&#8217;s do this the agile way. What I&#8217;d like to do is complete a timeboxed spike (in terms of actual time spent learning the language, not calendar time &#8211; I&#8217;m doing this in my spare time, and I&#8217;ve got my wife, four kids, and three other side projects competing for my attention!) of roughly two weeks in each language. The first week of the spike would be spent getting comfortable with the syntax, reading articles/documentation/blogs/etc., writing &#8220;Hello, World!&#8221; etc. The second week of the spike would be spent solving the same problem in each language, preferably a problem sitting in the functional sweet spot.</p>
<p>How does this sound to everyone? And to follow up, does anyone have a suggested problem I might tackle? Cheers!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mattstine.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mattstine.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mattstine.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mattstine.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mattstine.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mattstine.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mattstine.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mattstine.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mattstine.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mattstine.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mattstine.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mattstine.wordpress.com/117/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mattstine.wordpress.com/117/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mattstine.wordpress.com/117/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=117&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mattstine.com/2009/04/06/lotypart-deux/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1eaa45fee6a2b0c4b479b2982a4274f4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mattstine</media:title>
		</media:content>

		<media:content url="http://mattstine.files.wordpress.com/2009/04/scala_vs_clojure.jpg" medium="image">
			<media:title type="html">scala_vs_clojure</media:title>
		</media:content>
	</item>
		<item>
		<title>LOTY Time Again: Scala or Clojure?!?!</title>
		<link>http://mattstine.com/2009/04/02/loty-time-again-scala-or-clojure/</link>
		<comments>http://mattstine.com/2009/04/02/loty-time-again-scala-or-clojure/#comments</comments>
		<pubDate>Thu, 02 Apr 2009 20:21:21 +0000</pubDate>
		<dc:creator>mattstine</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[dynamiclanguages]]></category>
		<category><![CDATA[goals]]></category>
		<category><![CDATA[grails]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.mattstine.com/?p=113</guid>
		<description><![CDATA[In 2007 I established several professional development goals (and later reported my progress on these), one of which was to learn Groovy and Grails. This goal stemmed from the continually referenced idea from The Pragmatic Programmer to &#8220;learn a new language every year.&#8221; This idea has become so ubiquitous that it even has it&#8217;s own [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=113&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In 2007 <a href="http://www.mattstine.com/2007/07/10/my-professional-development-goals-for-2007-2008/">I established several professional development goals</a> (<a href="http://www.mattstine.com/2008/01/02/mid-year-review-my-professional-development-goals-for-2007-2008/">and later reported my progress on these</a>), one of which was to learn Groovy and Grails. This goal stemmed from the continually referenced idea from <em>The Pragmatic Programmer</em> to &#8220;learn a new language every year.&#8221; This idea has become so ubiquitous that it even has it&#8217;s own four-letter acronym, LOTY (Language of the Year).</p>
<p>Since establishing and reporting on these goals, I&#8217;ve had several things get in the way of fully realizing all of them. However, I can safely say that in the last two years I have mastered enough Groovy and Grails that they no longer fit in the LOTY category. At this point they&#8217;re really not showing my anything that is causing any paradigm shifts for me. They&#8217;re comfortable. When I learn a new feature, it just seems to make sense, and nothing surprises me anymore. Languages like these aren&#8217;t good LOTY candidates because one of the purposes of learning a LOTY is to challenge and change your ideas about programming. Groovy doesn&#8217;t do this for me anymore. It&#8217;s time to move on (not to say that I&#8217;m dropping Groovy and Grails as a tool &#8211; I&#8217;m using them more now than ever &#8211; they&#8217;re just not a learning tool for me anymore).</p>
<p>So, at this point I want to delve into a language that attempts to tackle the concurrent/multicore programming challenge. I&#8217;d like to stay on the JVM because I appreciate the benefits that it brings as a platform, so for now Erlang is out. The two leading candidates in the JVM/concurrent/multicore arena seem to be <a href="http://www.scala-lang.org/">Scala</a> and <a href="http://clojure.org/">Clojure</a>. An added benefit of both of these languages is that they support the functional paradigm, something I haven&#8217;t really played with since my computer science education days and a very interesting language named Haskell.</p>
<p>Scala is a multiparadigm language, supporting both object-oriented and functional constructs. It is statically typed, yet offers very nice type inference. Clojure, on the other hand, is a functional Lisp derivative with almost no OO constructs that is dynamically typed. Both are designed to enable concurrent programming. Which one do I choose? I open the floor for comments.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mattstine.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mattstine.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mattstine.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mattstine.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mattstine.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mattstine.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mattstine.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mattstine.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mattstine.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mattstine.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mattstine.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mattstine.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mattstine.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mattstine.wordpress.com/113/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=113&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mattstine.com/2009/04/02/loty-time-again-scala-or-clojure/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1eaa45fee6a2b0c4b479b2982a4274f4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mattstine</media:title>
		</media:content>
	</item>
		<item>
		<title>The Developer Iteration</title>
		<link>http://mattstine.com/2009/04/01/the-developer-iteration/</link>
		<comments>http://mattstine.com/2009/04/01/the-developer-iteration/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 21:56:59 +0000</pubDate>
		<dc:creator>mattstine</dc:creator>
				<category><![CDATA[agile]]></category>
		<category><![CDATA[CodeProject]]></category>

		<guid isPermaLink="false">http://www.mattstine.com/?p=96</guid>
		<description><![CDATA[I recently gave a 90 minute talk at work covering quite a bit of ground related to Agile Software Development. If I had to sum up agile development in one word, it would be FEEDBACK. Venkat Subramaniam and Andy Hunt give one of the best definitions of agile I&#8217;ve ever seen in their book, Practices [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=96&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I recently gave a 90 minute talk at work covering quite a bit of ground related to Agile Software Development. If I had to sum up agile development in one word, it would be FEEDBACK. Venkat Subramaniam and Andy Hunt give one of the best definitions of agile I&#8217;ve ever seen in their book, <em>Practices of an Agile Developer</em>:</p>
<blockquote><p><em>Agile development uses feedback to make constant adjustments in a highly collaborative environment.</em></p></blockquote>
<p>Here&#8217;s my graphical representation of this quote:</p>
<p style="text-align:center;"><img class="size-medium wp-image-98 aligncenter" title="Agile Feedback Loop" src="http://mattstine.files.wordpress.com/2009/04/aws_fb_1012.jpg?w=300&#038;h=225" alt="Agile Feedback Loop" width="300" height="225" /></p>
<p>I decomposed this into an &#8220;ecosystem&#8221; of multiple feedback loops:</p>
<p style="text-align:center;"><img class="size-medium wp-image-100 aligncenter" title="Developer to Code" src="http://mattstine.files.wordpress.com/2009/04/aws_fb_2013.jpg?w=300&#038;h=225" alt="Developer to Code" width="300" height="225" /></p>
<p style="text-align:center;"><img class="size-medium wp-image-101 aligncenter" title="Developer to Developer" src="http://mattstine.files.wordpress.com/2009/04/aws_fb_3025.jpg?w=300&#038;h=225" alt="Developer to Developer" width="300" height="225" /></p>
<p style="text-align:center;"><img class="size-medium wp-image-102 aligncenter" title="Team to Client" src="http://mattstine.files.wordpress.com/2009/04/aws_fb_4033.jpg?w=300&#038;h=225" alt="Team to Client" width="300" height="225" /></p>
<p>What I&#8217;d like to focus on in this post is what I consider to be the heart of the &#8220;Developer to Code&#8221; feedback loop: <strong>The Developer Iteration</strong>.</p>
<p>You see, iterations aren&#8217;t just for teams. Indeed they are also for developers. So many times I have witnessed individuals struggling to participate fully in an agile project because when they return to their desks, for all intents and purposes, they are pretending to be a waterfall. They spend days analyzing a feature, code for days without sharing any code, test the happy path toward the end of the iteration, and attempt a big bang integration on the last day. I&#8217;ll be the first to admit that I myself tried to code this way and had a couple of realizations after a short time:</p>
<ul>
<li>Something felt completely unnatural about it, especially in the context of what we were trying to do as a team&#8230;</li>
<li>I was awfully miserable, especially at the end of the iteration.</li>
</ul>
<p>So, what does the developer iteration look like? It is essentially a microcosm of events that occur during a regular team iteration:</p>
<ol>
<li>Look at your feature or task, and plan out what you have to do.</li>
<li>Break the work into small chunks, where each chunk leaves the system in a stable state, yet that much closer to the feature or task being complete.</li>
<li>Develop each chunk (preferably using Test-Driven Development), unit and integration testing your work along the way.</li>
<li>Check-in your code EVERY TIME you again arrive at a stable state.</li>
</ol>
<p>I&#8217;ll give my definition of stability: A system with NO broken tests. How do we maintain stability? Here are several &#8220;smaller&#8221; steps that should immediately proceed your check-in step:</p>
<ol>
<li>Run the tests on your development machine, fixing all broken ones until you reach 100% passing with the code you have.</li>
<li>Check out the latest code from your version control system, thereby integrating your team&#8217;s changes with your own.</li>
<li>Run the tests AGAIN, fixing all broken ones until you reach 100% passing with the integrated code. At this point, your system is stable locally.</li>
<li>Check-in the code! Now the entire team has a stable, fully-integrated system.</li>
</ol>
<p>So, what&#8217;s the point of all this? Look at how much feedback you&#8217;re giving yourself along the way! Each time you stop and run the tests, you&#8217;re getting feedback about the stability of your code. Not only that, but your constant striving for 100% stability greatly enhances your ability to refactor your code to keep it clean. You&#8217;re able to constantly refine the code, creating smaller methods, more cohesive classes, and an overall simpler and better design combined with the confidence that your system is functionally equivalent to what you started with prior to refactoring.</p>
<p>Yet another benefit is an enhanced ability to timebox yourself. Working this way enhances your ability to plan to be &#8220;done&#8221; by the end of the day, as you&#8217;re never very far from your next stable state. Go home with a stable system, and find a stable system when you get back in the morning. Doesn&#8217;t that feel great? Even if you can&#8217;t reach a stable state by the time you head home, there&#8217;s always the throwaway option. Just revert your changes and go home with stable code. Try again with a fresh mind the next morning. Again, if you&#8217;re working the developer iteration, you haven&#8217;t written that much code since your last stable state anyway. <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Try it out. I&#8217;m not a salesman. I&#8217;m a satisfied customer.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mattstine.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mattstine.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mattstine.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mattstine.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mattstine.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mattstine.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mattstine.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mattstine.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mattstine.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mattstine.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mattstine.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mattstine.wordpress.com/96/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mattstine.wordpress.com/96/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mattstine.wordpress.com/96/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=96&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mattstine.com/2009/04/01/the-developer-iteration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1eaa45fee6a2b0c4b479b2982a4274f4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mattstine</media:title>
		</media:content>

		<media:content url="http://mattstine.files.wordpress.com/2009/04/aws_fb_1012.jpg?w=300" medium="image">
			<media:title type="html">Agile Feedback Loop</media:title>
		</media:content>

		<media:content url="http://mattstine.files.wordpress.com/2009/04/aws_fb_2013.jpg?w=300" medium="image">
			<media:title type="html">Developer to Code</media:title>
		</media:content>

		<media:content url="http://mattstine.files.wordpress.com/2009/04/aws_fb_3025.jpg?w=300" medium="image">
			<media:title type="html">Developer to Developer</media:title>
		</media:content>

		<media:content url="http://mattstine.files.wordpress.com/2009/04/aws_fb_4033.jpg?w=300" medium="image">
			<media:title type="html">Team to Client</media:title>
		</media:content>
	</item>
		<item>
		<title>Deploying Grails with Groovy</title>
		<link>http://mattstine.com/2009/03/29/deploying-grails-with-groovy/</link>
		<comments>http://mattstine.com/2009/03/29/deploying-grails-with-groovy/#comments</comments>
		<pubDate>Sun, 29 Mar 2009 08:38:09 +0000</pubDate>
		<dc:creator>mattstine</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[grails]]></category>
		<category><![CDATA[groovy]]></category>

		<guid isPermaLink="false">http://www.mattstine.com/?p=89</guid>
		<description><![CDATA[Interesting title, eh? Maybe this one will make it through Glen&#8217;s filter at GroovyBlogs.org. On to the meat. I&#8217;ve been steadily working on a couple of Grails applications, one being the website for the Memphis JUG, and another being the e-commerce site for my wife&#8217;s soon to be launched designer stationery business. Just like your [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=89&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Interesting title, eh? Maybe this one will make it through Glen&#8217;s filter at <a href="http://groovyblogs.org">GroovyBlogs.org</a>.</p>
<p>On to the meat. I&#8217;ve been steadily working on a couple of Grails applications, one being the website for the <a href="http://www.memphisjug.org">Memphis JUG</a>, and another being the e-commerce site for my wife&#8217;s soon to be launched designer stationery business. Just like your average Grails developer, I&#8217;ve been happily coding away at 127.0.0.1 using the good old development Jetty+MySQL stack. Well, in the last week or so it&#8217;s come time to actually deploy both of these applications into production. I started out last weekend with the Memphis JUG site. My first approach was to build the WAR file locally and then &#8220;scp&#8221; it up to the server.</p>
<p>YMMV, but the upload speed on my DSL connection is horrible! After doing this three or four times in one night, waiting 15-20 minutes for the WAR to upload each time (Grails WAR&#8217;s are rather thick when carrying all of the dependencies along), I decided to myself, &#8220;There must be a better way to do this.&#8221;</p>
<p>Fast forward a week and here I sit working on the first &#8220;pre-production&#8221; release of my wife&#8217;s store site. With quite a bit of time on my hands during these &#8220;dark and early&#8221; hours (a story for a later entry), I decided it was time for the experiment.</p>
<p>Each of these projects is hosted at GitHub, so the process that I mapped out in my mind looked like this:</p>
<ol>
<li>Check out the latest code from GitHub</li>
<li>Run &#8220;grails war&#8221;</li>
<li>Stop the Tomcat service (my hosting provider sets up Tomcat to run as a service)</li>
<li>Delete the remnants of the previous deployment from Tomcat&#8217;s deployment directory</li>
<li>Copy the new WAR file to Tomcat&#8217;s deployment directory</li>
<li>Start the Tomcat service</li>
</ol>
<p>By the way, I forgot to mention that before doing all of this I moved the production data source definition from being locally defined to being a JNDI lookup within Tomcat. This posed its own challenge, which I&#8217;ll blog about a bit later.</p>
<p>Anyway, back to the deployment. I though this would be an excellent opportunity to take <a href="http://groovy.codehaus.org/Using+Ant+from+Groovy">Groovy&#8217;s Antbuilder</a> out for a spin. Here&#8217;s an example of what I put together:</p>
<pre class="brush: groovy">
#!/usr/bin/env groovy

def ant = new AntBuilder()

//Update the codebase from GitHub
ant.exec(executable:'git', dir: "${PROJECT_DIR}") {
        arg(value:'pull')
}

//Generate the WAR file using Ant
ant.ant(dir:'"${PROJECT_DIR}"', target: 'war')

//Stop Tomcat
ant.exec(executable:'service') {
        arg(line:'tomcat6 stop')
}

//Delete the old webapp contents from Tomcat's deploy directory
ant.delete(includeemptydirs:'true', verbose:'true') {
        fileset(dir:"${CONTEXT_ROOT_DIR}", includes:'**/*')
}

//Copy the new WAR file to Tomcat's deploy directory
ant.copy(file:"${WAR_FILE}", tofile:"${CONTEXT_ROOT_DIR}/ROOT.war")

//Start Tomcat
ant.exec(executable:'service') {
        arg(line:'tomcat6 start')
}
</pre>
<p>As you can see, I have a few undefined Groovy constants in there. Let&#8217;s just say I didn&#8217;t want to expose ALL of the details of my server.</p>
<p>At any rate, it&#8217;s pretty simple. One word of warning &#8211; if you&#8217;re using Ehcache, make sure to add it to your ivy.xml dependencies, or the Ant build won&#8217;t bring it in like running &#8220;grails war&#8221; will. I hope someone finds this simple script useful. Enjoy!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mattstine.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mattstine.wordpress.com/89/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mattstine.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mattstine.wordpress.com/89/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mattstine.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mattstine.wordpress.com/89/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mattstine.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mattstine.wordpress.com/89/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mattstine.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mattstine.wordpress.com/89/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mattstine.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mattstine.wordpress.com/89/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mattstine.wordpress.com/89/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mattstine.wordpress.com/89/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=89&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mattstine.com/2009/03/29/deploying-grails-with-groovy/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1eaa45fee6a2b0c4b479b2982a4274f4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mattstine</media:title>
		</media:content>
	</item>
		<item>
		<title>Need a Textile engine? Look no further than Plextile!</title>
		<link>http://mattstine.com/2009/03/26/need-a-textile-engine-look-no-further-than-plextile/</link>
		<comments>http://mattstine.com/2009/03/26/need-a-textile-engine-look-no-further-than-plextile/#comments</comments>
		<pubDate>Thu, 26 Mar 2009 21:23:46 +0000</pubDate>
		<dc:creator>mattstine</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[grails]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[textile]]></category>

		<guid isPermaLink="false">http://www.mattstine.com/?p=81</guid>
		<description><![CDATA[In finishing up the first release of JUG Nexus, the open source engine (http://github.com/mstine/jug-nexus/tree/master) behind the new Memphis JUG website, I needed to put a good Textile engine in place. I really don&#8217;t care for writing actual HTML in a content management system, and JUG Nexus being a lightweight CMS, I wanted a lightweight markup [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=81&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In finishing up the first release of JUG Nexus, the open source engine (<a href="http://github.com/mstine/jug-nexus/tree/master">http://github.com/mstine/jug-nexus/tree/master</a>) behind the new Memphis JUG website, I needed to put a good <a href="http://www.textism.com/tools/textile/">Textile</a> engine in place. I really don&#8217;t care for writing actual HTML in a content management system, and JUG Nexus being a lightweight CMS, I wanted a lightweight markup syntax for entering the details of upcoming JUG meetings. Textile is exactly that, and is also used for entering content into the very useful <a href="http://jugevents.org">JUGEvents</a> system produced by <a href="http://www.jugpadova.it/">JUG Padova</a> for the Java User Group community at large. I tried out several different engines, and none of them seemed to be very robust when it came to edge cases in the markup. For example, if I want to produce a hyperlink to a website, the textile format is the following:</p>
<p><code><br />
"Linked Text":http://www.site.com<br />
</code></p>
<p>This syntax will result in the following HTML:</p>
<pre class="brush: xml">
&lt;a href="http://www.site.com"&gt;Linked Text&lt;/a&gt;
</pre>
<p>Unfortunately, if you have a bang (!) in your &#8220;Linked Text,&#8221; most of the Textile engines that I used would not recognize it as an HTML link. Plextile does!</p>
<p>The only drawback, however minimal, to using Plextile is that it does not come with a pre-packaged JAR file. You have to take the compiled code and JAR it yourself. Now, for free, I&#8217;ll include how I integrated Plextile with Grails. Grails has a very nice codec feature that provides a facility to register encoders and decoders of textual data as methods on any object. Grails searches for classes following the convention <code>XCodec</code> and dynamically registers <code>encodeAsX</code> and <code>decodeX</code> methods on <code>java.lang.Object</code> so that any data can be encoded and decoded. Enter the <code>TextileCodec</code>:</p>
<pre class="brush: groovy">
import com.plink.plextile.TextParser

class TextileCodec {

   static encode = {str -&gt;
      new TextParser().parseTextile(str, true)
   }

}
</pre>
<p>Believe it or not, that&#8217;s it! Here&#8217;s the GSP template for rendering a JUG meeting:</p>
<pre class="brush: xml">
&lt;div class="post"&gt;
  &lt;h2&gt;${event.title}&lt;br/&gt;&lt;br/&gt;&lt;g:formatDate format="EEEE, MMMM dd, yyyy" date="${event.startTime}"/&gt;&lt;br/&gt;&lt;g:formatDate format="h:mm" date="${event.startTime}"/&gt;-&lt;g:formatDate format="h:mm a" date="${event.endTime}"/&gt;&lt;br/&gt;&lt;g:if test="${!event.archived}"&gt;&lt;a href="http://jugevents.org/jugevents/event/${event.jugEventsId}"&gt;Click HERE to register!&lt;/a&gt;&lt;/g:if&gt;&lt;/h2&gt;
  &lt;div class="entry"&gt;
    &lt;h2 class="title"&gt;Speaker/Topic:&lt;/h2&gt;
    &lt;p&gt;${event.description.encodeAsTextile()}&lt;/p&gt;
    &lt;h2 class="title"&gt;Location/Directions:&lt;/h2&gt;
    &lt;p&gt;${event.location}&lt;/p&gt;
    &lt;p&gt;${event.directions.encodeAsTextile()}&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;
</pre>
<p>Enjoy!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mattstine.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mattstine.wordpress.com/81/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mattstine.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mattstine.wordpress.com/81/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mattstine.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mattstine.wordpress.com/81/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mattstine.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mattstine.wordpress.com/81/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mattstine.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mattstine.wordpress.com/81/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mattstine.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mattstine.wordpress.com/81/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mattstine.wordpress.com/81/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mattstine.wordpress.com/81/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=81&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mattstine.com/2009/03/26/need-a-textile-engine-look-no-further-than-plextile/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1eaa45fee6a2b0c4b479b2982a4274f4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mattstine</media:title>
		</media:content>
	</item>
		<item>
		<title>The Manifesto for Software Craftsmanship</title>
		<link>http://mattstine.com/2009/03/15/the-manifesto-for-software-craftsmanship/</link>
		<comments>http://mattstine.com/2009/03/15/the-manifesto-for-software-craftsmanship/#comments</comments>
		<pubDate>Mon, 16 Mar 2009 03:45:00 +0000</pubDate>
		<dc:creator>mattstine</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.mattstine.com/?p=69</guid>
		<description><![CDATA[So as I&#8217;m sitting here thumbing through my InfoQ feed on Google Reader, I come across the following posting: Software Craftsmanship Manifesto: A Call to Arms. It seems that a group of &#8220;programming patriots&#8221; has struck again (see the Manifesto for Agile Software Development &#8211; circa 2001), complete with a &#8220;founding document&#8221; look and feel. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=69&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://5386.openphoto.net"><img src="http://openphoto.net/cgi-bin/image?image_id=5386" width="251" height="193" style="float:left;padding-right:10px;"></a>So as I&#8217;m sitting here thumbing through my <a href="http://www.infoq.com">InfoQ</a> feed on <a href="http://www.google.com/reader">Google Reader</a>, I come across the following posting: <a href="http://www.infoq.com/news/2009/03/software_craftsmanship">Software Craftsmanship Manifesto: A Call to Arms</a>. It seems that a group of &#8220;programming patriots&#8221; has struck again (see the <a href="http://agilemanifesto.org">Manifesto for Agile Software Development</a> &#8211; circa 2001), complete with a &#8220;founding document&#8221; look and feel. Clicking through <a href="http://manifesto.softwarecraftsmanship.org/">the source link</a>, one finds the following:</p>
<blockquote><p>As aspiring Software Craftsmen we are raising the bar of professional software development by practicing it and helping others learn the craft. Through this work we have come to value:
<ul>
<li>Not only working software, but also well-crafted software</li>
<p>
<li>Not only responding to change, but also steadily adding value</li>
<p>
<li>Not only individuals and interactions, but also a community of professionals</li>
<p>
<li>Not only customer collaboration,but also productive partnerships</li>
<p></ul>
<p>That is, in pursuit of the items on the left we have found the items on the right to be indispensable.</p>
<p>© 2009, the undersigned. this statement may be freely copied in any form, but only in its entirety through this notice.</p></blockquote>
<p>You can&#8217;t even imagine my excitement in reading this. This statement of values is something that I have been trying to get across without having the needed words for quite some time. </p>
<p>The motivation, says the InfoQ article, is right on target:</p>
<blockquote><p>The members of the manifesto group answered two key questions: “How will it help solve the problems of crap code?” and “What will motivate &#8220;The developer just churning out code&#8221; to become a craftsman?” &#8211; the distinction is between the developer who is just getting it done vs the one getting it done right.</p></blockquote>
<p>I have felt for a long time that the elements of craftsmanship are something sorely missing from our field. We, as programmers, are often so consumed with getting the job done that we do often neglect getting it done right. In our haste to move on to the next exciting project and/or technology, we neglect the tenets of simple design, test-driven development, merciless refactoring, clean code, etc. We&#8217;re often quite satisfied with the &#8220;hacky solution here&#8221; and the &#8220;quick and dirty solution there.&#8221;</p>
<p>Quite frankly, I&#8217;ve had enough of that. I&#8217;m not satisfied when the contractor building my house cuts corners. I&#8217;m quite irritable when my mechanic does a less than thorough job with my car. Why should I expect my clients to settle for software built like that?</p>
<p>So, to make this a practical rant, I thought I&#8217;d share a couple of the things that we&#8217;re doing in our team to move us in the right direction:
<ol>
<li>First of all, we started a weekly &#8220;brown bag lunch/workshop,&#8221; inspired by Andy Hunt and Venkat Subramaniam&#8217;s discussion in <span style="font-style:italic;"><a href="http://pragprog.com/titles/pad/practices-of-an-agile-developer">Practices of an Agile Developer</a></span>.</li>
<p>
<li>Second, we selected books to read as a team that will point us in the right direction. Our first two titles were <span style="font-style:italic;"><a href="http://pragprog.com/titles/tpp/the-pragmatic-programmer">The Pragmatic Programmer: From Journeyman to Master</a></span> (see, there&#8217;s craftsmanship right away!) and <span style="font-style:italic;"><a href="http://www.pearsonhighered.com/educator/academic/product/1,3110,0132350882,00.html">Clean Code: A Handbook of Agile Software Craftsmanship</a></span> (sense a pattern yet?).</li>
<p>
<li>Third, we make a point of our weekly discussions to look at ways we can integrate the principles and practices that we&#8217;re learning into our daily work. An example: We&#8217;re working to integrate peer code review into our development process. The principles, patterns, and practices that we&#8217;re picking up from <span style="font-style:italic;">Clean Code</span> will be informing us as we review code and look for possible improvements.</li>
<p></ol>
<p>So, with that said, tonight I became a signatory of the manifesto. <a href="http://manifesto.softwarecraftsmanship.org/sign/new">Why don&#8217;t you join me and fight the fight against crappy code!</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mattstine.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mattstine.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mattstine.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mattstine.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mattstine.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mattstine.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mattstine.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mattstine.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mattstine.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mattstine.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mattstine.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mattstine.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mattstine.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mattstine.wordpress.com/69/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=69&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mattstine.com/2009/03/15/the-manifesto-for-software-craftsmanship/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1eaa45fee6a2b0c4b479b2982a4274f4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mattstine</media:title>
		</media:content>

		<media:content url="http://openphoto.net/cgi-bin/image?image_id=5386" medium="image" />
	</item>
		<item>
		<title>Grails+Dojo Ajax File Upload</title>
		<link>http://mattstine.com/2009/03/13/grailsdojo-ajax-file-upload/</link>
		<comments>http://mattstine.com/2009/03/13/grailsdojo-ajax-file-upload/#comments</comments>
		<pubDate>Sat, 14 Mar 2009 03:08:00 +0000</pubDate>
		<dc:creator>mattstine</dc:creator>
				<category><![CDATA[CodeProject]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.mattstine.com/?p=68</guid>
		<description><![CDATA[I&#8217;m currently working on a Grails application with a requirement for uploading product images, which are subsequently resized into thumbnails of various sizes for different shopping screens. Since it took a bit of doing to get this done, I thought I&#8217;d post my solution here in case anyone could benefit from it. First, to set [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=68&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently working on a <a href="http://grails.org/">Grails</a> application with a requirement for uploading product images, which are subsequently resized into thumbnails of various sizes for different shopping screens. Since it took a bit of doing to get this done, I thought I&#8217;d post my solution here in case anyone could benefit from it.</p>
<p>First, to set the stage, I&#8217;ve upgraded the application all the way to the newly released <a href="http://www.springsource.org/node/1107">Grails 1.1</a>.</p>
<p>To start off, I naively attempted to use the built-in Prototype library to do the upload with a simple <code>&lt;g:submitRemote/&gt;</code> tag. You might have guessed that this didn&#8217;t work at all. Continuing to learn the hard way (without reading the manual I might add), I submitted this as a bug to the Grails project. Graeme ever so politely informed me that this was known and expected behavior, as Prototype doesn&#8217;t support such a thing. However, it was Graeme that also tipped me off to try Dojo.</p>
<p>So, continuing down this path, I proceeded to install the Grails Dojo plugin. Once this is done, a <code>&lt;g:javascript library="dojo"/&amp;gt</code> is supposedly all that is required to convert your Ajax calls from Prototype to Dojo. This turned out to not be the case for me, with Javascript errors popping up all over the place, not the least of which was that dojo.js seemed to be installed in an unexpected location via the plugin. The hacker in me simply copied this to the expected location and moved along. However, as I attempted to work with Dojo&#8217;s file upload support, I discovered that the version of Dojo shipped with the plugin seemed at first glance to be way behind. Frustrated by this, I went ahead and stripped the Dojo plugin out and installed <a href="http://download.dojotoolkit.org/release-1.2.3/dojo.js">the latest version available (at this writing 1.2.3)</a>, and set about to develop my solution.</p>
<p>Here goes:</p>
<p><strong>1. Add the necessary Dojo dependencies to your GSP:</strong></p>
<pre class="brush: js; html-script: true">
&lt;script type="text/javascript" src="${createLinkTo(dir: 'js/dojo', file: 'dojo.js')}"
   djConfig="parseOnLoad:true, isDebug:true"&gt;&lt;/script&gt;
&lt;g:javascript&gt;
   dojo.require("dojo.io.iframe");
&lt;/g:javascript&gt;
</pre>
<p><strong>2. Write a function using dojo.io.iframe to send the form:</strong></p>
<pre class="brush: js">
function submitForm() {
   dojo.io.iframe.send({
      form: 'uploadProductImageForm',
      load: function (data) {
         dojo.byId('productImage').innerHTML = data;
      }
   });
}
</pre>
<p><strong>3. Create the file upload form:</strong></p>
<pre class="brush: xml">
&lt;g:form name="uploadProductImageForm" method="post" action="uploadProductImage" enctype="multipart/form-data"&gt;
   &lt;input type="hidden" name="id" value="${productInstance?.id}"/&gt;
   &lt;input type="file" name="newProductImage"/&gt;
   &lt;span class="button"&gt;&lt;input class="add" type="button" name="uploadImage" value="Upload Image" onclick="submitForm()"/&gt;&lt;/span&gt;
&lt;/g:form&gt;
</pre>
<p><strong>4. Create the controller method:</strong></p>
<pre class="brush: groovy">
def uploadProductImage = {
   def f = request.getFile('newProductImage')
   if (!f.empty) {

   def imagePath = grailsApplication.config.store.productImages.location

   //Create unique name for this image set based on current timestamp
   def name = "image" + new Date().getTime()

   //Store the file
   def file = new File("${imagePath}/${originalFilename}")
   f.transferTo(file)

   //Do some image processing (resizing, etc.)
   ...

   //Dojo requires returning the result nested in an HTML document containing a body and textarea tag. Do this with
   //Groovy's built-in MarkupBuilder

   def writer = new StringWriter()
   def xml = new MarkupBuilder(writer)

   xml.html {
     body {
       textarea {
         img(src: resource(dir: grailsApplication.config.store.productImages.webPath, file: product.mediumImage.name), width: '250')
       }
     }
   }

   render writer.toString()
   }
   else {
      flash.message = 'file cannot be empty'
      redirect(action: show)
   }
}
</pre>
<p>And there you have it. Let me know what you think of this solution. It definitely works for me. You will notice that I didn&#8217;t include an upload progress bar &#8211; I&#8217;ll be doing this in a future iteration of the project. Cheers!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mattstine.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mattstine.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mattstine.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mattstine.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/mattstine.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/mattstine.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/mattstine.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/mattstine.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mattstine.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mattstine.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mattstine.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mattstine.wordpress.com/68/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mattstine.wordpress.com/68/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mattstine.wordpress.com/68/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mattstine.com&amp;blog=58954&amp;post=68&amp;subd=mattstine&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mattstine.com/2009/03/13/grailsdojo-ajax-file-upload/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1eaa45fee6a2b0c4b479b2982a4274f4?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mattstine</media:title>
		</media:content>
	</item>
	</channel>
</rss>
