<?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>Ted Naleid</title>
	<atom:link href="http://naleid.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://naleid.com/blog</link>
	<description>Groovy, Grails and OS X tips and tricks</description>
	<lastBuildDate>Wed, 03 Mar 2010 04:24:16 +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>Updated grails autocomplete script for zsh</title>
		<link>http://naleid.com/blog/2010/03/02/updated-grails-autocomplete-script-for-zsh/</link>
		<comments>http://naleid.com/blog/2010/03/02/updated-grails-autocomplete-script-for-zsh/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 04:22:28 +0000</pubDate>
		<dc:creator>tednaleid</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://naleid.com/blog/?p=166</guid>
		<description><![CDATA[A couple of years ago, I created a grails auto-completion script for bash and zsh.  
Since then, I&#8217;ve completely abandoned bash, in favor of zsh (which I consider to be the superior shell) and I&#8217;d been getting annoyed at a few issues in the last grails autocomplete script.
I finally got motivated to make some [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of years ago, I created a <a href="http://naleid.com/blog/2008/03/25/autocomplete-grails-script-names-in-bashzsh/">grails auto-completion script for bash and zsh</a>.  </p>
<p>Since then, I&#8217;ve completely abandoned bash, <a href="http://naleid.com/blog/2009/05/13/shared-zshrc-file/">in favor of zsh</a> (which I consider to be the superior shell) and I&#8217;d been getting annoyed at a few issues in the last grails autocomplete script.</p>
<p>I finally got motivated <a href="http://bitbucket.org/tednaleid/shared-zshrc/src/tip/zshrc_grails_compinstall" onclick="pageTracker._trackPageview('/outgoing/bitbucket.org/tednaleid/shared-zshrc/src/tip/zshrc_grails_compinstall?referer=');">to make some enhancements to it</a>.  Including support for grails 1.2 plugin scripts (1.2 moved the plugins into the ~/.grails directory), and support for test class name autocompletion (very useful for <code>grails test-app</code>).</p>
<p>To get it working (assuming you&#8217;re using zsh), you can either add the contents of <a href="http://bitbucket.org/tednaleid/shared-zshrc/src/tip/zshrc_grails_compinstall" onclick="pageTracker._trackPageview('/outgoing/bitbucket.org/tednaleid/shared-zshrc/src/tip/zshrc_grails_compinstall?referer=');">my zshrc_grails_compinstall</a> to your .zshrc file, or you can switch over to using <a href="http://naleid.com/blog/2009/05/13/shared-zshrc-file/">my full zshrc setup</a>, which has a number of nice features that I&#8217;ve collected over the years.  I&#8217;ll also continue to update this as I think of new tricks.</p>
<p>After getting it installed, just type &#8220;grails&#8221; followed by a space and then hit tab.  It will show you a list of all of the potential grails scripts for the application that you&#8217;re in.  It&#8217;s aware of the version of the current app, as well as it&#8217;s application name based on the contents of application.properties, and also will include any scripts for the plugins you have installed in that app in <code>~/.grails/GRAILS_VERSION/projects/APP_NAME/plugins</code>  (in addition to the scripts in <code>./scripts</code>, <code>$GRAILS_HOME/scripts</code> and <code>~/.grails/scripts</code>).</p>
<p>After you choose your script (such as <code>grails test-app</code> hit space again and it will show you all of the test classes, with the full package for the class, under your test directory.</p>
]]></content:encoded>
			<wfw:commentRss>http://naleid.com/blog/2010/03/02/updated-grails-autocomplete-script-for-zsh/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using iWork Numbers.app AppleScript to Sum Columns For All Tables on a Sheet</title>
		<link>http://naleid.com/blog/2010/02/07/using-iwork-numbers-applescript-to-sum-columns-for-all-tables-on-a-sheet/</link>
		<comments>http://naleid.com/blog/2010/02/07/using-iwork-numbers-applescript-to-sum-columns-for-all-tables-on-a-sheet/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 04:45:08 +0000</pubDate>
		<dc:creator>tednaleid</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://naleid.com/blog/?p=157</guid>
		<description><![CDATA[Overall, I&#8217;m pretty happy with Numbers.app (part of Apple&#8217;s iWork suite) as a replacement for Excel.  It&#8217;s considerably cheaper and has lots of user interface tweaks to make it more pleasant to work with.
One of these changes is that each sheet can actually have multiple tables on it, and these can be arranged independently [...]]]></description>
			<content:encoded><![CDATA[<p>Overall, I&#8217;m pretty happy with Numbers.app (part of Apple&#8217;s iWork suite) as a replacement for Excel.  It&#8217;s considerably cheaper and has lots of user interface tweaks to make it more pleasant to work with.</p>
<p>One of these changes is that each sheet can actually have multiple tables on it, and these can be arranged independently on the same page.  This prevents the problem that happens in excel where you have multiple sets of data you want to see at the same time, but the cell/row sizing for one set of data affects the data in the other set that happens to be on the same row.</p>
<p>I&#8217;ve been leveraging this for a one-off personal project and I had a need to sum up all of the data in the 2nd column on all of the tables within a particular sheet.</p>
<p>This brought me to <a href="http://developer.apple.com/mac/library/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html" onclick="pageTracker._trackPageview('/outgoing/developer.apple.com/mac/library/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html?referer=');">AppleScript</a>, Apple&#8217;s scripting language that&#8217;s used to drive applications.<br />
<span id="more-157"></span><br />
You can write scripts in the AppleScript editor (found in /Applications/Utilities).  In there, you can look up the commands and objects that a particular program makes available by going to File->Open Dictionary and then finding the application that you want to script.</p>
<p>I&#8217;ve done a little work in AppleScript in the past, but always recoil from it when I&#8217;m done.  It&#8217;s so damn wordy in what appears to be an attempt to make it more &#8220;friendly&#8221; when it really just makes it harder to remember the right syntax to get something done.  It probably just has <a href="http://www.youtube.com/watch?v=dCud8H7z7vU" onclick="pageTracker._trackPageview('/outgoing/www.youtube.com/watch?v=dCud8H7z7vU&amp;referer=');">&#8220;too many notes&#8221;.</a></p>
<p>Regardless, here&#8217;s the script that I came up with to sum up all of the values in the 2nd column (Column B) for all of the tables on the currently active sheet and then insert the result onto the 2nd column of a table named &#8220;Totals&#8221; (which must previously exist).</p>

<div class="wp_syntax"><div class="code"><pre class="applescript" style="font-family:monospace;"><span style="color: #ff0033; font-weight: bold;">tell</span> <span style="color: #0066ff;">application</span> <span style="color: #009900;">&quot;Numbers&quot;</span>
	<span style="color: #ff0033; font-weight: bold;">tell</span> <span style="color: #0066ff;">document</span> <span style="color: #000000;">1</span>
		<span style="color: #ff0033; font-weight: bold;">set</span> total <span style="color: #ff0033; font-weight: bold;">to</span> <span style="color: #000000;">0</span>
		<span style="color: #ff0033; font-weight: bold;">set</span> totalTable <span style="color: #ff0033; font-weight: bold;">to</span> <span style="color: #000000;">0</span>
		<span style="color: #ff0033; font-weight: bold;">tell</span> sheet <span style="color: #000000;">1</span>
			<span style="color: #ff0033; font-weight: bold;">repeat</span> <span style="color: #ff0033; font-weight: bold;">with</span> j <span style="color: #ff0033; font-weight: bold;">from</span> <span style="color: #000000;">1</span> <span style="color: #ff0033; font-weight: bold;">to</span> <span style="color: #000000;">&#40;</span><span style="color: #0066ff;">count</span> <span style="color: #ff0033; font-weight: bold;">of</span> tables<span style="color: #000000;">&#41;</span>
				<span style="color: #ff0033; font-weight: bold;">try</span>
					<span style="color: #ff0033; font-weight: bold;">tell</span> table j
						<span style="color: #ff0033; font-weight: bold;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #0066ff;">name</span> <span style="color: #ff0033; font-weight: bold;">is</span> <span style="color: #ff0033;">not</span> <span style="color: #ff0033;">equal</span> <span style="color: #ff0033; font-weight: bold;">to</span> <span style="color: #009900;">&quot;Totals&quot;</span><span style="color: #000000;">&#41;</span> <span style="color: #ff0033; font-weight: bold;">then</span>
							<span style="color: #ff0033; font-weight: bold;">repeat</span> <span style="color: #ff0033; font-weight: bold;">with</span> k <span style="color: #ff0033; font-weight: bold;">from</span> <span style="color: #000000;">1</span> <span style="color: #ff0033; font-weight: bold;">to</span> <span style="color: #0066ff;">count</span> <span style="color: #ff0033; font-weight: bold;">of</span> rows
								<span style="color: #ff0033; font-weight: bold;">set</span> total <span style="color: #ff0033; font-weight: bold;">to</span> total <span style="color: #000000;">+</span> <span style="color: #000000;">&#40;</span>value <span style="color: #ff0033; font-weight: bold;">of</span> cell <span style="color: #000000;">2</span> <span style="color: #ff0033; font-weight: bold;">of</span> row k<span style="color: #000000;">&#41;</span>
							<span style="color: #ff0033; font-weight: bold;">end</span> <span style="color: #ff0033; font-weight: bold;">repeat</span>
						<span style="color: #ff0033; font-weight: bold;">else</span>
							<span style="color: #ff0033; font-weight: bold;">set</span> totalTable <span style="color: #ff0033; font-weight: bold;">to</span> j
						<span style="color: #ff0033; font-weight: bold;">end</span> <span style="color: #ff0033; font-weight: bold;">if</span>
					<span style="color: #ff0033; font-weight: bold;">end</span> <span style="color: #ff0033; font-weight: bold;">tell</span>
				<span style="color: #ff0033; font-weight: bold;">end</span> <span style="color: #ff0033; font-weight: bold;">try</span>
			<span style="color: #ff0033; font-weight: bold;">end</span> <span style="color: #ff0033; font-weight: bold;">repeat</span>
			<span style="color: #ff0033; font-weight: bold;">tell</span> table totalTable
				<span style="color: #0066ff;">display dialog</span> <span style="color: #009900;">&quot;total = &quot;</span> <span style="color: #000000;">&amp;</span> total <span style="color: #000000;">&amp;</span> <span style="color: #009900;">&quot; total table = &quot;</span> <span style="color: #000000;">&amp;</span> totalTable
				<span style="color: #ff0033; font-weight: bold;">set</span> value <span style="color: #ff0033; font-weight: bold;">of</span> cell <span style="color: #000000;">2</span> <span style="color: #ff0033; font-weight: bold;">of</span> row <span style="color: #000000;">1</span> <span style="color: #ff0033; font-weight: bold;">to</span> total
			<span style="color: #ff0033; font-weight: bold;">end</span> <span style="color: #ff0033; font-weight: bold;">tell</span>
		<span style="color: #ff0033; font-weight: bold;">end</span> <span style="color: #ff0033; font-weight: bold;">tell</span>
	<span style="color: #ff0033; font-weight: bold;">end</span> <span style="color: #ff0033; font-weight: bold;">tell</span>
<span style="color: #ff0033; font-weight: bold;">end</span> <span style="color: #ff0033; font-weight: bold;">tell</span></pre></div></div>

<p>I needed this ability as the number of tables on this sheet will change quite frequently depending on what I&#8217;m doing with it, and the values in the 2nd column of each of these tables will also get frequently modified and I need to easily know the sum across all of the tables.</p>
<p>To actually execute the script within Numbers.app, there are a couple of ways to do it.  It doesn&#8217;t appear that Numbers has it&#8217;s own script directory (normally, it would be under ~/Library/Application Support/iWork/Numbers/Scripts), but you can add it to your own User Scripts directory at ~/Library/Scripts.</p>
<p>If you want to access it through your menus, you can enable the global script icon up there by going into the AppleScript Editor preferences.  On the General tab, check the box that says &#8220;Show Script menu in menu bar&#8221;.</p>
<p>If you&#8217;re using LaunchBar or Quicksilver, you can also add this directory to their catalog as a place to search.  Then it&#8217;s as easy as cmd-space and the name of the script to execute it (both apps also allow you to set up keyboard shortcuts too).</p>
<p>In all, it feels hacky, and I&#8217;m sure it could be improved if I actually knew what the hell I was doing in AppleScript, but as I said, it&#8217;s a one-off that I need for a fairly particular problem.</p>
<p>I should probably take a little more time to learn more about AppleScript (or look more closely at a bridge to a language that I find a bit more palatable).  Being able to script the applications that I use can be very useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://naleid.com/blog/2010/02/07/using-iwork-numbers-applescript-to-sum-columns-for-all-tables-on-a-sheet/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Interrogating Arbitrary Groovy Closures for Values</title>
		<link>http://naleid.com/blog/2010/01/24/interrogating-arbitrary-groovy-closures-for-values/</link>
		<comments>http://naleid.com/blog/2010/01/24/interrogating-arbitrary-groovy-closures-for-values/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 01:24:25 +0000</pubDate>
		<dc:creator>tednaleid</dc:creator>
				<category><![CDATA[grails]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[metaprogramming]]></category>

		<guid isPermaLink="false">http://naleid.com/blog/?p=136</guid>
		<description><![CDATA[Inspired by this question on stackoverflow, I decided to create a utility class that allowed me to determine generically what calls a closure makes (without actually letting it make any calls).  This lets me see what it&#8217;s trying to do before letting it actually do it.

It works by overriding the delegate of the closure [...]]]></description>
			<content:encoded><![CDATA[<p>Inspired by <a href="http://stackoverflow.com/questions/2128115/access-values-of-static-closure-in-groovy" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/2128115/access-values-of-static-closure-in-groovy?referer=');">this question on stackoverflow</a>, I decided to create a utility class that allowed me to determine generically what calls a closure makes (without actually letting it make any calls).  This lets me see what it&#8217;s trying to do before letting it actually do it.<br />
<span id="more-136"></span><br />
It works by overriding the delegate of the closure (a delegate intercepts all method and property get/set calls that have not already been dealt with).  It assigns it to an instance of the ClosureInterrogator which implements the propertyMissing and methodMissing methods.  Any property or set method that is called gets saved in a map that is returned to the caller.</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> ClosureInterrogator <span style="color: #669966;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #aaaadd; font-weight: bold;">Map</span> closureValueMap <span style="color: #669966;">=</span> <span style="color: #669966;">&#91;</span>:<span style="color: #669966;">&#93;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #aaaadd; font-weight: bold;">Map</span> extractValuesFromClosure<span style="color: #669966;">&#40;</span>Closure closure<span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">def</span> interrogator <span style="color: #669966;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ClosureInterrogator<span style="color: #669966;">&#40;</span>closure<span style="color: #669966;">&#41;</span>
        <span style="color: #000000; font-weight: bold;">return</span> interrogator.<span style="color: #006600;">closureValueMap</span>
    <span style="color: #669966;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> ClosureInterrogator<span style="color: #669966;">&#40;</span>Closure closure<span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">def</span> oldResolveStrategy <span style="color: #669966;">=</span> closure.<span style="color: #006600;">getResolveStrategy</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
        <span style="color: #000000; font-weight: bold;">def</span> oldDelegate <span style="color: #669966;">=</span> closure.<span style="color: #006600;">getDelegate</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
        closure.<span style="color: #006600;">delegate</span> <span style="color: #669966;">=</span> <span style="color: #000000; font-weight: bold;">this</span>
        closure.<span style="color: #006600;">resolveStrategy</span> <span style="color: #669966;">=</span> Closure.<span style="color: #006600;">DELEGATE_FIRST</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #669966;">&#123;</span>
            closure<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
        <span style="color: #669966;">&#125;</span> <span style="color: #000000; font-weight: bold;">finally</span> <span style="color: #669966;">&#123;</span>        
            closure.<span style="color: #006600;">setDelegate</span><span style="color: #669966;">&#40;</span>oldDelegate<span style="color: #669966;">&#41;</span>
            closure.<span style="color: #006600;">setResolveStrategy</span><span style="color: #669966;">&#40;</span>oldResolveStrategy<span style="color: #669966;">&#41;</span>
        <span style="color: #669966;">&#125;</span>
    <span style="color: #669966;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">// property getter</span>
    <span style="color: #000000; font-weight: bold;">def</span> propertyMissing<span style="color: #669966;">&#40;</span><span style="color: #aaaadd; font-weight: bold;">String</span> name<span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> closureValueMap<span style="color: #669966;">&#91;</span>name<span style="color: #669966;">&#93;</span>
    <span style="color: #669966;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">// property setter</span>
    <span style="color: #000000; font-weight: bold;">def</span> propertyMissing<span style="color: #669966;">&#40;</span><span style="color: #aaaadd; font-weight: bold;">String</span> name, value<span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        closureValueMap<span style="color: #669966;">&#91;</span>name<span style="color: #669966;">&#93;</span> <span style="color: #669966;">=</span> value
    <span style="color: #669966;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> methodMissing<span style="color: #669966;">&#40;</span><span style="color: #aaaadd; font-weight: bold;">String</span> name, args<span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        <span style="color: #996600;">if</span> <span style="color: #669966;">&#40;</span>args.<span style="color: #663399;">size</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">==</span> <span style="color: #cc66cc;">1</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
            closureValueMap<span style="color: #669966;">&#91;</span>name<span style="color: #669966;">&#93;</span> <span style="color: #669966;">=</span> args<span style="color: #669966;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #669966;">&#93;</span>
        <span style="color: #669966;">&#125;</span> <span style="color: #996600;">else</span> <span style="color: #669966;">&#123;</span>
            closureValueMap<span style="color: #669966;">&#91;</span>name<span style="color: #669966;">&#93;</span> <span style="color: #669966;">=</span> args
        <span style="color: #669966;">&#125;</span>
    <span style="color: #669966;">&#125;</span>
<span style="color: #669966;">&#125;</span></pre></div></div>

<p>This technique is the basis for all groovy mocking techniques and libraries, it&#8217;s also the main technique used to create a <acronym title="Domain Specific Language">DSL</acronym> with groovy.</p>
<p>Here is a sample class that has a closure (&#8220;something&#8221;) that we want to extract the values from.</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> SomeClass <span style="color: #669966;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">static</span> something <span style="color: #669966;">=</span> <span style="color: #669966;">&#123;</span>
        key1 <span style="color: #aa0000;">&quot;value1&quot;</span>              <span style="color: #808080; font-style: italic;">// calls methodMissing(&quot;key1&quot;, [&quot;value1&quot;])</span>
        key2<span style="color: #669966;">&#40;</span><span style="color: #aa0000;">&quot;value2&quot;</span><span style="color: #669966;">&#41;</span>             <span style="color: #808080; font-style: italic;">// calls methodMissing(&quot;key2&quot;, [&quot;value2&quot;])</span>
        key3 <span style="color: #669966;">=</span> <span style="color: #aa0000;">&quot;value3&quot;</span>            <span style="color: #808080; font-style: italic;">// calls propertyMissing(&quot;key3&quot;, &quot;value3&quot;)</span>
        key4 <span style="color: #aa0000;">&quot;foo&quot;</span>, <span style="color: #aa0000;">&quot;bar&quot;</span>, <span style="color: #aa0000;">&quot;baz&quot;</span>   <span style="color: #808080; font-style: italic;">// calls methodMissing(&quot;key4&quot;, [&quot;foo&quot;,&quot;bar&quot;,&quot;baz&quot;])</span>
    <span style="color: #669966;">&#125;</span>
<span style="color: #669966;">&#125;</span></pre></div></div>

<p>If we call &#8220;extractValuesFromClosure&#8221; on the &#8220;something&#8221; closure, we&#8217;ll get back a map that has all of the values we want in it.</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">def</span> closureValueMap <span style="color: #669966;">=</span> ClosureInterrogator.<span style="color: #006600;">extractValuesFromClosure</span><span style="color: #669966;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> SomeClass<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>.<span style="color: #006600;">something</span><span style="color: #669966;">&#41;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">assert</span> <span style="color: #aa0000;">&quot;value1&quot;</span> <span style="color: #669966;">==</span> closureValueMap.<span style="color: #aa0000;">&quot;key1&quot;</span>  <span style="color: #808080; font-style: italic;">// calls propertyMissing(&quot;key1&quot;)</span>
<span style="color: #000000; font-weight: bold;">assert</span> <span style="color: #aa0000;">&quot;value2&quot;</span> <span style="color: #669966;">==</span> closureValueMap.<span style="color: #aa0000;">&quot;key2&quot;</span>  <span style="color: #808080; font-style: italic;">// calls propertyMissing(&quot;key2&quot;)</span>
<span style="color: #000000; font-weight: bold;">assert</span> <span style="color: #aa0000;">&quot;value3&quot;</span> <span style="color: #669966;">==</span> closureValueMap.<span style="color: #aa0000;">&quot;key3&quot;</span>  <span style="color: #808080; font-style: italic;">// calls propertyMissing(&quot;key3&quot;)</span>
<span style="color: #000000; font-weight: bold;">assert</span> <span style="color: #669966;">&#91;</span><span style="color: #aa0000;">&quot;foo&quot;</span>, <span style="color: #aa0000;">&quot;bar&quot;</span>, <span style="color: #aa0000;">&quot;baz&quot;</span><span style="color: #669966;">&#93;</span> <span style="color: #669966;">==</span> closureValueMap.<span style="color: #aa0000;">&quot;key4&quot;</span>  <span style="color: #808080; font-style: italic;">// calls propertyMissing(&quot;key4&quot;)</span></pre></div></div>

<p>This class will work with any type of closure, such as this closure used by the <a href="http://www.grails.org/Mail+plugin" onclick="pageTracker._trackPageview('/outgoing/www.grails.org/Mail+plugin?referer=');">grails mail plugin</a> to send mail.</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">def</span> mailClosure <span style="color: #669966;">=</span> <span style="color: #669966;">&#123;</span>
   to <span style="color: #aa0000;">&quot;fred@g2one.com&quot;</span>,<span style="color: #aa0000;">&quot;ginger@g2one.com&quot;</span>
   from <span style="color: #aa0000;">&quot;john@g2one.com&quot;</span>
   cc <span style="color: #aa0000;">&quot;marge@g2one.com&quot;</span>, <span style="color: #aa0000;">&quot;ed@g2one.com&quot;</span>
   bcc <span style="color: #aa0000;">&quot;joe@g2one.com&quot;</span>
   subject <span style="color: #aa0000;">&quot;Hello John&quot;</span>
   body <span style="color: #aa0000;">'this is some text'</span>
<span style="color: #669966;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">def</span> results <span style="color: #669966;">=</span> ClosureInterrogator.<span style="color: #006600;">extractValuesFromClosure</span><span style="color: #669966;">&#40;</span>mailClosure<span style="color: #669966;">&#41;</span>
<span style="color: #663366;">println</span> results
<span style="color: #808080; font-style: italic;">// prints:</span>
<span style="color: #808080; font-style: italic;">// [to:[fred@g2one.com, ginger@g2one.com], from:john@g2one.com, cc:[marge@g2one.com, ed@g2one.com], bcc:joe@g2one.com, subject:Hello John, body:this is some text]</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">assert</span> results.<span style="color: #006600;">to</span>.<span style="color: #006600;">every</span> <span style="color: #669966;">&#123;</span> it.<span style="color: #006600;">endsWith</span><span style="color: #669966;">&#40;</span><span style="color: #aa0000;">&quot;g2one.com&quot;</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#125;</span></pre></div></div>

<p>If we wanted to assert that within a test environment, we&#8217;re only sending e-mail to a specific domain, this would be one technique to assert it before we actually send the e-mail off.</p>
<p>ClosureInterrogator is generic enough that it could also be used on a number of Grails/GORM domain closures such as &#8220;constraints&#8221; and &#8220;mapping&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://naleid.com/blog/2010/01/24/interrogating-arbitrary-groovy-closures-for-values/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Hooking up Hudson to your bitbucket mercurial account</title>
		<link>http://naleid.com/blog/2009/12/21/hooking-up-hudson-to-your-bitbucket-mercurial-account/</link>
		<comments>http://naleid.com/blog/2009/12/21/hooking-up-hudson-to-your-bitbucket-mercurial-account/#comments</comments>
		<pubDate>Mon, 21 Dec 2009 06:29:12 +0000</pubDate>
		<dc:creator>tednaleid</dc:creator>
				<category><![CDATA[hudson]]></category>

		<guid isPermaLink="false">http://naleid.com/blog/?p=113</guid>
		<description><![CDATA[This past weekend, I saw @wakaleo running into some issues getting bitbucket hooked up to hudson.
I responded with a long reply that I thought would be worth cleaning up and posting here.

Mercurial, Bitbucket and Hudson
I&#8217;ve been using Mercurial as my personal revision control system for a while now.
I&#8217;ve more recently been using it at work [...]]]></description>
			<content:encoded><![CDATA[<p>This past weekend, I saw <a href="http://twitter.com/wakaleo" onclick="pageTracker._trackPageview('/outgoing/twitter.com/wakaleo?referer=');">@wakaleo</a> running into <a href="http://twitter.com/wakaleo/status/6789413053" onclick="pageTracker._trackPageview('/outgoing/twitter.com/wakaleo/status/6789413053?referer=');">some issues getting bitbucket hooked up to hudson</a>.</p>
<p>I <a href="http://twitter.com/tednaleid/status/6800126659" onclick="pageTracker._trackPageview('/outgoing/twitter.com/tednaleid/status/6800126659?referer=');">responded</a> with <a href="http://a.longreply.com/248600" onclick="pageTracker._trackPageview('/outgoing/a.longreply.com/248600?referer=');">a long reply</a> that I thought would be worth cleaning up and posting here.<br />
<span id="more-113"></span></p>
<h3>Mercurial, Bitbucket and Hudson</h3>
<p>I&#8217;ve been using <a href="http://mercurial.selenic.com/" onclick="pageTracker._trackPageview('/outgoing/mercurial.selenic.com/?referer=');">Mercurial</a> as my personal revision control system <a href="http://naleid.com/blog/2008/11/25/my-mercurial-setup-plus-some-useful-shims-and-jigs/">for a</a> <a href="http://naleid.com/blog/2009/11/08/mercurial-dvcs-devjam-presentation/">while now</a>.</p>
<p>I&#8217;ve more recently been using it at work with a repository hosted at <a href="http://bitbucket.org/" onclick="pageTracker._trackPageview('/outgoing/bitbucket.org/?referer=');">BitBucket</a>, a great service that offers free accounts (including one private repo) and very <a href="http://bitbucket.org/plans/" onclick="pageTracker._trackPageview('/outgoing/bitbucket.org/plans/?referer=');">reasonable upgraded accounts</a>.   (I don&#8217;t have any relationship with bitbucket other than just as a happy and satisfied user.)</p>
<p>Being a good agile shop, we use <a href="http://hudson-ci.org/" onclick="pageTracker._trackPageview('/outgoing/hudson-ci.org/?referer=');">hudson</a> as our <a href="http://martinfowler.com/articles/continuousIntegration.html" onclick="pageTracker._trackPageview('/outgoing/martinfowler.com/articles/continuousIntegration.html?referer=');">continuous integration</a> server (much better than Cruise Control IMO).  It polls the source control repository on a periodic basis, if it sees any code changes, it checks them out and runs all of the tests.</p>
<h3> Quick Mercurial/Hudson Setup</h3>
<h5>Install Mercurial</h5>
<p>There are lots of ways to <a href="http://mercurial.selenic.com/wiki/Download" onclick="pageTracker._trackPageview('/outgoing/mercurial.selenic.com/wiki/Download?referer=');">install mercurial</a>.  On the Ubuntu box, the quickest way to get a recent version for me was to just use python&#8217;s easy_install:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> easy_install mercurial</pre></div></div>

<h5>Install Hudson</h5>
<p>There are better guides out there for getting Hudson going depending on the platform you&#8217;re using, but here&#8217;s the quick instructions for how I got it going on an Ubuntu 9.10 image running on Amazon EC2.</p>
<p>Using Ubuntu&#8217;s apt-get package management, installing hudson is easy.  You need to add the repository that has the hudson source so that apt-get knows where to get it.  Add this to your <code>/etc/apt/sources.list</code> file:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">deb http:<span style="color: #000000; font-weight: bold;">//</span>hudson-ci.org<span style="color: #000000; font-weight: bold;">/</span>debian binary<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>

<p>Then update apt-get and install hudson:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> update
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> hudson</pre></div></div>

<p>That creates a hudson install with a new &#8220;hudson&#8221; user on your system.  </p>
<h3>Setting up Hudson to SSH</h3>
<p>We want this user to be able to connect to BitBucket over SSH and check out the repository.  To do this, we&#8217;ll need an ssh public and private key that hudson can use.  Sudo to the hudson user and generate one:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">su</span> - hudson
&nbsp;
<span style="color: #666666; font-style: italic;"># cd to the home dir, default in /var/lib/hudson</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> ~
&nbsp;
<span style="color: #666666; font-style: italic;"># create the ssh key in the ~/.ssh directory</span>
<span style="color: #c20cb9; font-weight: bold;">ssh-keygen</span> <span style="color: #660033;">-t</span> rsa
&nbsp;
<span style="color: #666666; font-style: italic;"># that creates the public/private key in the /var/lib/hudson.ssh directory</span>
<span style="color: #c20cb9; font-weight: bold;">cat</span> ~<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span>id_rsa.pub</pre></div></div>

<p>Copy that key to your clipboard (make sure to get all of it, it&#8217;s all one big line that probably has wrapped in your terminal window a couple of times).  We&#8217;ll be using this as our identification on bitbucket.</p>
<h5>Give the Public Key to BitBucket</h5>
<p>If you&#8217;ve already got a BitBucket account that you want to give Hudson access to go to it now.  Otherwise, create a new account for Hudson to use.  Go to the <a href="http://bitbucket.org/account/" onclick="pageTracker._trackPageview('/outgoing/bitbucket.org/account/?referer=');">&#8220;account&#8221; page</a> and paste the public key in the &#8220;SSH Keys&#8221; field and hit the &#8220;add key&#8221; button.</p>
<p>If this is the account that owns the repository (or already has access to it), you&#8217;re done on BitBucket.  Otherwise, if it&#8217;s a private repository owned by another user, you&#8217;ll need to add the hudson bitbucket user as a &#8220;read-only&#8221; user to the repository on the repository&#8217;s &#8220;admin&#8221; screen (or ask the repo owner to do that).</p>
<p>Then, go to the repository and get the ssh clone string for the repo you want to clone.  By default, bitbucket shows you the HTTPS clone string, which will NOT work with this authentication method.  To see it, click on the &#8220;SSH&#8221; link and it should show you something like:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">hg clone <span style="color: #c20cb9; font-weight: bold;">ssh</span>:<span style="color: #000000; font-weight: bold;">//</span>hg<span style="color: #000000; font-weight: bold;">@</span>bitbucket.org<span style="color: #000000; font-weight: bold;">/</span>tednaleid<span style="color: #000000; font-weight: bold;">/</span>grails-test-data<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>

<p>If the protocol in the url is &#8220;ssh&#8221;, you&#8217;ve got the right one.</p>
<h5>Finish Hudson Setup</h5>
<p>Back on the hudson box, you&#8217;ll want to manually clone the repo as the hudson user so that bitbucket is in the <code>~/.ssh/known_hosts</code> file.  Just execute the ssh clone command we found above:</p>
<p>Example:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">hg clone <span style="color: #c20cb9; font-weight: bold;">ssh</span>:<span style="color: #000000; font-weight: bold;">//</span>hg<span style="color: #000000; font-weight: bold;">@</span>bitbucket.org<span style="color: #000000; font-weight: bold;">/</span>tednaleid<span style="color: #000000; font-weight: bold;">/</span>grails-test-data<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>

<p>ssh will prompt you to add the host to the list of known hosts and then will clone the repo.  If that works, authentication is set up right and we&#8217;re almost done.</p>
<h5>Install the Mercurial plugin in Hudson</h5>
<p>All that&#8217;s left to do now is install the Mercurial plugin in hudson.  In a browser, go to http://INSERT_YOUR_IP_HERE:8080.  Hudson should come up.  </p>
<p>Click on &#8220;Manage Hudson&#8221; and go to &#8220;Manage Plugins&#8221;.  Go to the &#8220;Available&#8221; tab, check &#8220;Hudson Mercurial plugin&#8221; and hit the &#8220;Install&#8221; button.  Hudson will prompt you to restart, and then it&#8217;s installed.</p>
<p>After that, just create a new job and you&#8217;ll have a new &#8220;mercurial&#8221; option in the &#8220;source control management&#8221; section.  Select that and put the ssh URL in the &#8220;Repository URL&#8221; field.  Then put &#8220;default&#8221; in the &#8220;branch&#8221; field and set up the rest of the job to build/test your code (an exercise left to the reader).</p>
]]></content:encoded>
			<wfw:commentRss>http://naleid.com/blog/2009/12/21/hooking-up-hudson-to-your-bitbucket-mercurial-account/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mercurial DVCS DevJam Presentation</title>
		<link>http://naleid.com/blog/2009/11/08/mercurial-dvcs-devjam-presentation/</link>
		<comments>http://naleid.com/blog/2009/11/08/mercurial-dvcs-devjam-presentation/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 02:43:20 +0000</pubDate>
		<dc:creator>tednaleid</dc:creator>
				<category><![CDATA[command line]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[presentation]]></category>

		<guid isPermaLink="false">http://naleid.com/blog/?p=106</guid>
		<description><![CDATA[This past week, I gave a presentation to the DevJam meeting on the advantages of using Mercurial, a DVCS (Distributed Version Control System) over tools like Subversion, Perforce, and ClearCase.

I&#8217;ve been using a mercurial repository at bitbucket to host the build-test-data grails plugin, as well as a number of other things that I&#8217;ve done.  [...]]]></description>
			<content:encoded><![CDATA[<p>This past week, I gave a presentation to the <a href="http://www.devjam.com/" onclick="pageTracker._trackPageview('/outgoing/www.devjam.com/?referer=');">DevJam</a> meeting on the advantages of using Mercurial, a DVCS (Distributed Version Control System) over tools like Subversion, Perforce, and ClearCase.<br />
<span id="more-106"></span><br />
I&#8217;ve been using a mercurial repository at bitbucket to host the build-test-data grails plugin, as well as a number of other things that I&#8217;ve done.  We&#8217;re also using it at work to hold our grails applications.  I find that the way Mercurial works fits better with my style of development over git, the other popular DVCS.</p>
<p>The turnout at the meeting was great, and a heated discussion followed the presentation (as it always does at that meeting).</p>
<p>I&#8217;ve checked the original keynote files along with a PDF version into <a href="http://bitbucket.org/tednaleid/dvcs-with-mercurial/src/" onclick="pageTracker._trackPageview('/outgoing/bitbucket.org/tednaleid/dvcs-with-mercurial/src/?referer=');">a mercurial repository</a>.</p>
<p>Here&#8217;s <a href="http://www.slideshare.net/tednaleid/mercurial-dvcs-presentation-to-devjam-1142009-2426116" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/tednaleid/mercurial-dvcs-presentation-to-devjam-1142009-2426116?referer=');">the presentation on SlideShare</a>:</p>
<div style="width:425px;text-align:left" id="__ss_2426116"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/tednaleid/mercurial-dvcs-presentation-to-devjam-1142009-2426116" title="Mercurial DVCS presentation to DevJam 11/4/2009" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/tednaleid/mercurial-dvcs-presentation-to-devjam-1142009-2426116?referer=');">Mercurial DVCS presentation to DevJam 11/4/2009</a><object style="margin:0px" width="600" height="500"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=dvcspresentation-091104221655-phpapp01&#038;stripped_title=mercurial-dvcs-presentation-to-devjam-1142009-2426116" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=dvcspresentation-091104221655-phpapp01&#038;stripped_title=mercurial-dvcs-presentation-to-devjam-1142009-2426116" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="600" height="500"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/?referer=');">documents</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/tednaleid" onclick="pageTracker._trackPageview('/outgoing/www.slideshare.net/tednaleid?referer=');">tednaleid</a>.</div>
</div>
<p><script type="text/javascript">var dzone_style = '1';</script><br />
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> </p>
]]></content:encoded>
			<wfw:commentRss>http://naleid.com/blog/2009/11/08/mercurial-dvcs-devjam-presentation/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Grails Testing Alias to Rerun Failed Tests</title>
		<link>http://naleid.com/blog/2009/11/03/grails-testing-alias-to-rerun-failed-tests/</link>
		<comments>http://naleid.com/blog/2009/11/03/grails-testing-alias-to-rerun-failed-tests/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 03:29:58 +0000</pubDate>
		<dc:creator>tednaleid</dc:creator>
				<category><![CDATA[command line]]></category>
		<category><![CDATA[grails]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[shortcut]]></category>
		<category><![CDATA[unit testing]]></category>
		<category><![CDATA[zshrc]]></category>

		<guid isPermaLink="false">http://naleid.com/blog/?p=99</guid>
		<description><![CDATA[A while ago I blogged about my grails testing aliases and how much time they save me.
I&#8217;ve made some enhancements to them in the interim that have made them even easier to use.  
The most important alias is gtaf, which is short for &#8220;grails test-app&#8221; for failed tests.
It will search through your test output [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago I <a href="http://naleid.com/blog/2009/06/14/grails-testing-command-line-aliases/">blogged about my grails testing aliases</a> and how much time they save me.</p>
<p>I&#8217;ve made some enhancements to them in the interim that have made them even easier to use.  </p>
<p>The most important alias is <code>gtaf</code>, which is short for &#8220;grails test-app&#8221; for failed tests.</p>
<p>It will search through your test output directory and look for any tests that failed.  If it finds any, it will rerun only those tests.  Otherwise, it will rerun all tests.  That makes it easy to just use <code>gtaf</code> all the time.  If any tests fail, it will open them up using Console.app.  </p>
<p>If you&#8217;re not on OSX, or would like to use something else to view the failed test logs, just modify the <code>testlog</code> alias to do something different.<br />
<span id="more-99"></span><br />
There are alternative versions of it to only run failed integration tests (<code>gtaif</code> &#8211; Grails Test App Integration Failed), failed unit tests (<code>gtauf</code> &#8211; Grails Test App Unit Failed) or attach a debugger to the tests as they run (<code>gtadf</code> &#8211; Grails Test App Debug Failed).</p>
<p>These aliases, plus most of the rest of my zsh setup, is <a href="http://bitbucket.org/tednaleid/shared-zshrc/src/" onclick="pageTracker._trackPageview('/outgoing/bitbucket.org/tednaleid/shared-zshrc/src/?referer=');">available on bitbucket</a>.  If you haven&#8217;t used zsh before and are still using bash, I suggest <a href="http://naleid.com/blog/2009/05/13/shared-zshrc-file/">switching over for the numerous benefits that it gives you</a>.</p>
<p>Here&#8217;s the section of zshrc_general that has the grails testing aliases, just add this to your .zshrc/.bashrc and make sure to uncomment the appropriate GRAILS_TEST_LOG_DIRECTORY export if you&#8217;re not running grails 1.2 yet:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># grails &gt; 1.2</span>
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">GRAILS_TEST_LOG_DIRECTORY</span>=target<span style="color: #000000; font-weight: bold;">/</span>test-reports
&nbsp;
<span style="color: #666666; font-style: italic;"># grails &lt; 1.2</span>
<span style="color: #666666; font-style: italic;"># export GRAILS_TEST_LOG_DIRECTORY=test/reports</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># after grails-test if there were ERROR messages, you can open those logs with the Console.app using this</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">testlog</span>=<span style="color: #ff0000;">'for F in `grep -lE &quot;FAILED|Caused\ an\ ERROR&quot; $GRAILS_TEST_LOG_DIRECTORY/plain/*.txt`; do echo &quot;&gt;&gt;&gt; opening&quot; $F; open -a Console $F; done;'</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># grails-debug-suspend doesn't exist by default, it's a copy of grails-debug with the suspend flag changed to &quot;y&quot; so that</span>
<span style="color: #666666; font-style: italic;"># we can attach a remote debugger before it proceeds past startup</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># aliases where you can optionally pass in a set of tests to run (or no argument to run all tests in that group)</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gta</span>=grailsTestApp
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gtad</span>=grailsTestAppDebug
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gtau</span>=grailsTestAppUnit
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gtaud</span>=grailsTestAppUnitDebug
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gtai</span>=grailsTestAppIntegration
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gtaid</span>=grailsTestAppIntegrationDebug
&nbsp;
<span style="color: #666666; font-style: italic;"># aliases that will rerun any failed tests (or all tests if there aren't any failed tests)</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gtaf</span>=grailsTestAppFailed
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gtadf</span>=grailsTestAppDebugFailed
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gtauf</span>=grailsTestAppUnitFailed
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gtaudf</span>=grailsTestAppUnitDebugFailed
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gtaif</span>=grailsTestAppIntegrationFailed
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">gtaidf</span>=grailsTestAppIntegrationDebugFailed
&nbsp;
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> grailsTestApp<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsTest grails <span style="color: #ff0000;">&quot;&quot;</span> $<span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #000000; font-weight: bold;">function</span> grailsTestAppFailed<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsFailedTests grails <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> grailsTestAppDebug<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsTest grails-debug-suspend <span style="color: #ff0000;">&quot;&quot;</span> $<span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #000000; font-weight: bold;">function</span> grailsTestAppDebugFailed<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsFailedTests grails-debug-suspend <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> grailsTestAppUnit<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsTest grails <span style="color: #660033;">-unit</span> $<span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #000000; font-weight: bold;">function</span> grailsTestAppUnitFailed<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsFailedTests grails <span style="color: #660033;">-unit</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> grailsTestAppUnitDebug<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsTest grails-debug-suspend <span style="color: #660033;">-unit</span> $<span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #000000; font-weight: bold;">function</span> grailsTestAppUnitDebugFailed<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsFailedTests grails-debug-suspend <span style="color: #660033;">-unit</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> grailsTestAppIntegration<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsTest grails <span style="color: #660033;">-integration</span> $<span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #000000; font-weight: bold;">function</span> grailsTestAppIntegrationFailed<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsFailedTests grails <span style="color: #660033;">-integration</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> grailsTestAppIntegrationDebug<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsTest grails-debug-suspend <span style="color: #660033;">-integration</span> $<span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #000000; font-weight: bold;">function</span> grailsTestAppIntegrationDebugFailed<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> grailsFailedTests grails-debug-suspend <span style="color: #660033;">-integration</span> <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> grailsFailedTests<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #007800;">FAILED_TESTS</span>=<span style="color: #ff0000;">''</span>
	<span style="color: #000000; font-weight: bold;">for</span> F <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-lE</span> <span style="color: #ff0000;">&quot;FAILED|Caused\ an\ ERROR&quot;</span> <span style="color: #007800;">$GRAILS_TEST_LOG_DIRECTORY</span><span style="color: #000000; font-weight: bold;">/</span>plain<span style="color: #000000; font-weight: bold;">/*</span>.txt<span style="color: #000000; font-weight: bold;">`</span>; <span style="color: #000000; font-weight: bold;">do</span>
		<span style="color: #007800;">FAILED_TESTS</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$FAILED_TESTS</span> <span style="color: #780078;">`echo $F | sed -E 's/.*TEST-(.*)Tests.txt/\1/g'`</span>&quot;</span>
	<span style="color: #000000; font-weight: bold;">done</span>;
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;failed tests: <span style="color: #007800;">$FAILED_TESTS</span>&quot;</span>
	grailsTest $<span style="color: #000000;">1</span> $<span style="color: #000000;">2</span> <span style="color: #007800;">$FAILED_TESTS</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> grailsTest<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Running: $1 test-app $2 $3 || testlog &quot;</span>
    <span style="color: #000000; font-weight: bold;">time</span> $<span style="color: #000000;">1</span> test-app $<span style="color: #000000;">2</span> $<span style="color: #000000;">3</span> <span style="color: #000000; font-weight: bold;">||</span> testlog
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>I believe that they&#8217;ll also work fine as-is in bash, though I haven&#8217;t tested them.</p>
<p><script type="text/javascript">var dzone_style = '1';</script><br />
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> </p>
]]></content:encoded>
			<wfw:commentRss>http://naleid.com/blog/2009/11/03/grails-testing-alias-to-rerun-failed-tests/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Snow Leopard Shared Printer Job &#8220;On Hold: Authentication Required&#8221; fix</title>
		<link>http://naleid.com/blog/2009/11/01/snow-leopard-shared-printer-job-on-hold-authentication-required-fix/</link>
		<comments>http://naleid.com/blog/2009/11/01/snow-leopard-shared-printer-job-on-hold-authentication-required-fix/#comments</comments>
		<pubDate>Sun, 01 Nov 2009 19:18:16 +0000</pubDate>
		<dc:creator>tednaleid</dc:creator>
				<category><![CDATA[osx]]></category>

		<guid isPermaLink="false">http://naleid.com/blog/?p=95</guid>
		<description><![CDATA[I&#8217;ve had problems since installing snow leopard with sharing my printer with my wife&#8217;s macbook pro.
Whenever she&#8217;d try to print, the job would say &#8220;On Hold: Authentication Required&#8221;.  After some fiddling around I found a solution:

Go into System Preferences and go to the Print &#038; Fax panel.
Right click on the printer and choose &#8220;Reset [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had problems since installing snow leopard with sharing my printer with my wife&#8217;s macbook pro.</p>
<p>Whenever she&#8217;d try to print, the job would say &#8220;On Hold: Authentication Required&#8221;.  After some fiddling around I found a solution:</p>
<ol>
<li>Go into System Preferences and go to the Print &#038; Fax panel.</li>
<li>Right click on the printer and choose &#8220;Reset Printing System&#8230;&#8221;.  This will remove all of your printers.</li>
<li>Hit the &#8220;+&#8221; and add the printer back, it should now be reset and have fixed whatever was fubar before.</li>
<li>Click on the &#8220;Sharing Preferences&#8221; button (or go to the &#8220;Sharing&#8221; System Preference panel)</li>
<li>Make sure that &#8220;Printer Sharing&#8221; is checked and that your printer&#8217;s name is also checked and that &#8220;Everyone&#8221; is set to &#8220;Can Print&#8221;</li>
<li>On the remote machine you want to remove the printer and add it back in through the System Preferences Print &#038; Fax panel</li>
</ol>
<p>(This is on 10.6.1, not sure if this works in 10.6.0 (where I first had the problem), you should update to the latest).</p>
<p>After doing all that, I was able to print from my remote computers without any problems or any issues around authentication.</p>
]]></content:encoded>
			<wfw:commentRss>http://naleid.com/blog/2009/11/01/snow-leopard-shared-printer-job-on-hold-authentication-required-fix/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Grails Markdown Plugin 0.1 Released</title>
		<link>http://naleid.com/blog/2009/10/06/grails-markdown-plugin-0-1-released/</link>
		<comments>http://naleid.com/blog/2009/10/06/grails-markdown-plugin-0-1-released/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 05:46:10 +0000</pubDate>
		<dc:creator>tednaleid</dc:creator>
				<category><![CDATA[grails]]></category>
		<category><![CDATA[groovy]]></category>

		<guid isPermaLink="false">http://naleid.com/blog/?p=87</guid>
		<description><![CDATA[I&#8217;ve just released a quick plugin that I put together tonight to help render markdown text as HTML within a grails application.  It leverages the MarkdownJ library.
I&#8217;m a big fan of storing information in markdown format as it is easy to read, easy to write, and easy to transform.  A number of big [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just released a quick plugin that I put together tonight to help render <a href="http://en.wikipedia.org/wiki/Markdown" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Markdown?referer=');">markdown</a> text as HTML within a grails application.  It leverages the <a href="http://markdownj.org/" onclick="pageTracker._trackPageview('/outgoing/markdownj.org/?referer=');">MarkdownJ</a> library.</p>
<p>I&#8217;m a big fan of storing information in markdown format as it is easy to read, easy to write, and easy to transform.  A number of big websites like <a href="http://stackoverflow.com/editing-help" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/editing-help?referer=');">stackoverflow.com</a> support the entry and display of markdown text to help people format their questions and answers without having to remember to properly format HTML.</p>
<p>If you&#8217;re unfamiliar with <a href="http://en.wikipedia.org/wiki/Markdown" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Markdown?referer=');">Markdown</a> there are a number of <a href="http://stackoverflow.com/editing-help" onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/editing-help?referer=');">good</a> <a href="http://daringfireball.net/projects/markdown/syntax" onclick="pageTracker._trackPageview('/outgoing/daringfireball.net/projects/markdown/syntax?referer=');">references</a> on it&#8217;s use.</p>
<p>The grails markdown plugin is a very basic plugin.  Currently, it just wraps the markdown libarary with a single TagLib that lets you easily render html from a markdown string within your gsp pages.   </p>
<p>To install it, just type:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">grails install-plugin markdown</pre></div></div>

<p>To use it in your gsp file:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #669966;">&lt;</span>markdown:renderHtml<span style="color: #669966;">&gt;</span>
The <span style="color: #669966;">*</span>four<span style="color: #669966;">*</span> cardinal directions are
&nbsp;
<span style="color: #669966;">-</span> North
<span style="color: #669966;">-</span> South
<span style="color: #669966;">-</span> East
<span style="color: #669966;">-</span> West
<span style="color: #669966;">&lt;</span>/markdown:renderHtml<span style="color: #669966;">&gt;</span></pre></div></div>

<p>renders the html:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;p&gt;The &lt;em&gt;four&lt;/em&gt; cardinal directions are&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;North&lt;/li&gt;
    &lt;li&gt;South&lt;/li&gt;
    &lt;li&gt;East&lt;/li&gt;
    &lt;li&gt;West&lt;/li&gt;
&lt;/ul&gt;</pre></div></div>

<p>Or you can use the &#8220;text&#8221; attribute of the taglib:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #669966;">&lt;</span>markdown:renderHtml text<span style="color: #669966;">=</span><span style="color: #aa0000;">&quot;${post.body}&quot;</span>/<span style="color: #669966;">&gt;</span></pre></div></div>

<p>See the <a href="http://bitbucket.org/tednaleid/grails-markdown/wiki/Home" onclick="pageTracker._trackPageview('/outgoing/bitbucket.org/tednaleid/grails-markdown/wiki/Home?referer=');">Grails Markdown Wiki</a> and source for more details.</p>
<p><script type="text/javascript">var dzone_style = '1';</script><br />
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> </p>
]]></content:encoded>
			<wfw:commentRss>http://naleid.com/blog/2009/10/06/grails-markdown-plugin-0-1-released/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Batch Import Performance with Grails and MySQL</title>
		<link>http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/</link>
		<comments>http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/#comments</comments>
		<pubDate>Thu, 01 Oct 2009 05:53:47 +0000</pubDate>
		<dc:creator>tednaleid</dc:creator>
				<category><![CDATA[grails]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[batch]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://naleid.com/blog/?p=66</guid>
		<description><![CDATA[I&#8217;ve spent some time over the last couple of weeks working on a Grails service that allows us to import new records into our MySQL database.
A number of interesting techniques have popped out of this that I think would be useful for others doing similar types of importing using GORM/Hibernate/MySQL.
Background
For background, the imports in our [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve spent some time over the last couple of weeks working on a Grails service that allows us to import new records into our MySQL database.</p>
<p>A number of interesting techniques have popped out of this that I think would be useful for others doing similar types of importing using GORM/Hibernate/MySQL.<span id="more-66"></span></p>
<h2>Background</h2>
<p>For background, the imports in our app happen a few times a week, and range in size from less than a hundred up to a few hundred thousand new records.</p>
<p>It is also possible for us to get updates on previous data that we&#8217;ve imported, if a record in the import matches a record in our database, we  want to update the existing record rather than inserting a duplicate.</p>
<p>We had a desire to use a Grails service to do the importing as we could leverage our existing data model, plus, there are some special cases where the import logic can get a bit hairy and having access to all of our domain methods is nice.</p>
<p>If you&#8217;re doing much more frequent imports, with heavy performance requirements using millions to hundreds of millions of rows, you&#8217;ll likely want to look at another tool more specifically targeted for batch/ETL processes or writing something directly in Java.  For smaller jobs, you might be surprised how far you can get with groovy and grails.</p>
<h2>Example Naive Import Application</h2>
<p>To demonstrate the techniques, I&#8217;ve created a small test application.  This simple app only has Books.  It imports 100,000 randomly generated books in a single job (importing a Library of Books).  If our database already has a book with that ISBN and edition number, we want to update the title of previous book rather than creating a new book.</p>
<p>Here are the setup files that won&#8217;t change as we tweak our application.</p>
<p>The Domain class:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">// domain/Book.groovy</span>
<span style="color: #000000; font-weight: bold;">class</span> <span style="color: #aaaadd; font-weight: bold;">Book</span> <span style="color: #669966;">&#123;</span>
    <span style="color: #aaaadd; font-weight: bold;">String</span> title
    <span style="color: #aaaadd; font-weight: bold;">String</span> isbn
    <span style="color: #aaaadd; font-weight: bold;">Integer</span> edition
<span style="color: #669966;">&#125;</span></pre></div></div>

<p>The BookController that calls the service:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">// controller/BookController.groovy</span>
<span style="color: #000000; font-weight: bold;">class</span> BookController <span style="color: #669966;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> bookService
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> index <span style="color: #669966;">=</span> <span style="color: #669966;">&#123;</span> 
        <span style="color: #000000; font-weight: bold;">def</span> library <span style="color: #669966;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Library<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
        <span style="color: #000000; font-weight: bold;">def</span> startTime <span style="color: #669966;">=</span> <span style="color: #aaaadd; font-weight: bold;">System</span>.<span style="color: #006600;">currentTimeMillis</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>		
        bookService.<span style="color: #006600;">importBooksInLibrary</span><span style="color: #669966;">&#40;</span>library<span style="color: #669966;">&#41;</span>	
        render <span style="color: #aa0000;">&quot;time: ${(startTime - System.currentTimeMillis())/1000} seconds&quot;</span>
    <span style="color: #669966;">&#125;</span>
<span style="color: #669966;">&#125;</span></pre></div></div>

<p>And a Library class that&#8217;s the source of our books (don&#8217;t worry too much about the details of the Library class, just know that it&#8217;s the source of the fields that we&#8217;ll be importing.  For each book, it simply returns a map of the field values that should be saved or updated for the Book):</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Library <span style="color: #000000; font-weight: bold;">implements</span> <span style="color: #aaaadd; font-weight: bold;">Iterator</span> <span style="color: #669966;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">def</span> startTime <span style="color: #669966;">=</span> <span style="color: #aaaadd; font-weight: bold;">System</span>.<span style="color: #006600;">currentTimeMillis</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">def</span> lastBatchStarted <span style="color: #669966;">=</span> startTime
    <span style="color: #000000; font-weight: bold;">def</span> BOOKS_IN_LIBRARY <span style="color: #669966;">=</span> <span style="color: #cc66cc;">100000</span>
    <span style="color: #000000; font-weight: bold;">def</span> currentBook <span style="color: #669966;">=</span> <span style="color: #cc66cc;">1</span>
    <span style="color: #000000; font-weight: bold;">def</span> random <span style="color: #669966;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #aaaadd; font-weight: bold;">Random</span><span style="color: #669966;">&#40;</span><span style="color: #cc66cc;">12345</span><span style="color: #669966;">&#41;</span> <span style="color: #808080; font-style: italic;">// random generator with defined seed</span>
&nbsp;
    <span style="color: #aaaadd; font-weight: bold;">Iterator</span> iterator<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span> <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span> <span style="color: #000000; font-weight: bold;">as</span> <span style="color: #aaaadd; font-weight: bold;">Iterator</span> <span style="color: #669966;">&#125;</span>
    <span style="color: #993333;">boolean</span> hasNext<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span> currentBook <span style="color: #669966;">&lt;=</span> BOOKS_IN_LIBRARY <span style="color: #669966;">&#125;</span>
    <span style="color: #993333;">void</span> remove<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span> <span style="color: #669966;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">def</span> next<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        <span style="color: #996600;">if</span> <span style="color: #669966;">&#40;</span><span style="color: #669966;">!</span> <span style="color: #669966;">&#40;</span>currentBook <span style="color: #669966;">%</span> <span style="color: #cc66cc;">100</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#41;</span> printStatus<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #669966;">&#91;</span>
            title: <span style="color: #aa0000;">&quot;Book ${currentBook++}&quot;</span>,
            isbn: randomIsbn<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>, 
            edition: randomEdition<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
        <span style="color: #669966;">&#93;</span>
    <span style="color: #669966;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> randomIsbn<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        <span style="color: #808080; font-style: italic;">// one of 50,000 random isbn numbers</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #aa0000;">&quot;isbn-${random.nextInt(50000)}&quot;</span>
    <span style="color: #669966;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> randomEdition<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        <span style="color: #808080; font-style: italic;">// first through tenth editions</span>
        <span style="color: #000000; font-weight: bold;">return</span> random.<span style="color: #006600;">nextInt</span><span style="color: #669966;">&#40;</span><span style="color: #cc66cc;">9</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">+</span> <span style="color: #cc66cc;">1</span>
    <span style="color: #669966;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> printStatus<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">def</span> batchEnded <span style="color: #669966;">=</span> <span style="color: #aaaadd; font-weight: bold;">System</span>.<span style="color: #006600;">currentTimeMillis</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
        <span style="color: #000000; font-weight: bold;">def</span> seconds <span style="color: #669966;">=</span> <span style="color: #669966;">&#40;</span>batchEnded<span style="color: #669966;">-</span>lastBatchStarted<span style="color: #669966;">&#41;</span>/<span style="color: #cc66cc;">1000</span>
        <span style="color: #000000; font-weight: bold;">def</span> total <span style="color: #669966;">=</span> <span style="color: #669966;">&#40;</span>batchEnded<span style="color: #669966;">-</span>startTime<span style="color: #669966;">&#41;</span>/<span style="color: #cc66cc;">1000</span>
        <span style="color: #663366;">println</span> <span style="color: #aa0000;">&quot;Library Book $currentBook, last batch: ${seconds}s, total: ${total}s&quot;</span>
        lastBatchStarted <span style="color: #669966;">=</span> batchEnded
    <span style="color: #669966;">&#125;</span>
<span style="color: #669966;">&#125;</span></pre></div></div>

<p>The Library class is a proxy for whatever the source of your import info is (a .csv/excel file that you&#8217;re parsing through, a webservice, something posted to your server, etc.).</p>
<p>Also, to help see how we affect timing, every 100 books the Library prints out how long it took to process the last 100 books.</p>
<p>Here is the naive BookService that iterates through the Library that the BookController gives it.  For each book it receives a map of the books values.  It does a <code>findByIsbnAndEdition()</code> to see if the book already exists.  If it does, it updates it, otherwise it will create a new book:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> BookService <span style="color: #669966;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">def</span> importBooksInLibrary<span style="color: #669966;">&#40;</span>library<span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>		
        library.<span style="color: #663399;">each</span> <span style="color: #669966;">&#123;</span> <span style="color: #aaaadd; font-weight: bold;">Map</span> bookValueMap <span style="color: #669966;">-&gt;</span>
            updateOrInsertBook<span style="color: #669966;">&#40;</span>bookValueMap<span style="color: #669966;">&#41;</span>
        <span style="color: #669966;">&#125;</span>		
    <span style="color: #669966;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> updateOrInsertBook<span style="color: #669966;">&#40;</span><span style="color: #aaaadd; font-weight: bold;">Map</span> bookValueMap<span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">def</span> title <span style="color: #669966;">=</span> bookValueMap.<span style="color: #006600;">title</span>
        <span style="color: #000000; font-weight: bold;">def</span> isbn <span style="color: #669966;">=</span> bookValueMap.<span style="color: #006600;">isbn</span>
        <span style="color: #000000; font-weight: bold;">def</span> edition <span style="color: #669966;">=</span> bookValueMap.<span style="color: #006600;">edition</span>
        <span style="color: #000000; font-weight: bold;">def</span> existingBook <span style="color: #669966;">=</span> <span style="color: #aaaadd; font-weight: bold;">Book</span>.<span style="color: #006600;">findByIsbnAndEdition</span><span style="color: #669966;">&#40;</span>isbn, edition<span style="color: #669966;">&#41;</span>
&nbsp;
        <span style="color: #996600;">if</span> <span style="color: #669966;">&#40;</span>existingBook<span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span> <span style="color: #808080; font-style: italic;">// just update title</span>
            existingBook.<span style="color: #006600;">title</span> <span style="color: #669966;">=</span> title
            existingBook.<span style="color: #006600;">save</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
        <span style="color: #669966;">&#125;</span> <span style="color: #996600;">else</span> <span style="color: #669966;">&#123;</span> 
            <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #aaaadd; font-weight: bold;">Book</span><span style="color: #669966;">&#40;</span>bookValueMap<span style="color: #669966;">&#41;</span>.<span style="color: #006600;">save</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
        <span style="color: #669966;">&#125;</span>
    <span style="color: #669966;">&#125;</span>
<span style="color: #669966;">&#125;</span></pre></div></div>

<p>When you run this code, the first thing you notice is how slow it is.  The first 1000 records aren&#8217;t that bad.  On my old laptop they take about 7 seconds to insert.  After that things get slower and slower, books 10,000 to 11,000 take 20 seconds to insert.  Importing gets progressively worse as time goes on.  </p>
<p><img src="http://naleid.com/blog/wp-content/uploads/2009/09/performance_naive.png" alt="Naive Performance" /></p>
<p>Yikes!  It takes 2 hours and 36 minutes to import 100k records?  Over 3 minutes for the last thousand books to get imported? That can&#8217;t be right.</p>
<p>As it runs, if you open up your activity monitor/task manager/top application, you&#8217;ll also see that Grails is running very hot but also that MySQL&#8217;s CPU usage is slowly going up over time.</p>
<h2>MySQL Database Performance Tweaks</h2>
<h3>Start with the obvious: Database Indexes</h3>
<p>If you&#8217;ve done much database work, you know how much indexes can improve the speed of a query.  But how do you know what queries need indexes?</p>
<p>In some situations, like our example above, it can be fairly obvious.  We&#8217;re calling Book.findByIsbnAndEdition().  Chances are we need an index on the &#8220;book&#8221; table that includes the &#8220;isbn&#8221; and &#8220;edition&#8221; fields:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">INDEX</span> <span style="color: #ff0000;">`idx_book_isbn_edition`</span> <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #ff0000;">`book`</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`isbn`</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`edition`</span><span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<h4><small>What if it isn&#8217;t so obvious which queries need an index?</small></h4>
<p>There are a number of techniques available to us through grails to see what kind of SQL is getting executed.</p>
<h4><small>Turn on grails SQL logging</small></h4>
<p>Within grails, you can turn on SQL logging by putting this in your Config.groovy&#8217;s log4j closure:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;">trace <span style="color: #aa0000;">'org.hibernate.SQL'</span></pre></div></div>

<h4><small>Install the p6spy plugin and JDBC SQL profiler</small></h4>
<p>The <a href="http://grails.org/plugin/p6spy" onclick="pageTracker._trackPageview('/outgoing/grails.org/plugin/p6spy?referer=');">p6spy grails plugin</a> inserts a proxy between your database driver classes and Grails.  Because of this, it knows the full query, including the filled in query parameters and some timing information.</p>
<p>This is useful by itself, but you can have the p6spy plugin log it&#8217;s messages to a log4j socket appender that talks to the <a href="http://sourceforge.net/projects/sqlprofiler/" onclick="pageTracker._trackPageview('/outgoing/sourceforge.net/projects/sqlprofiler/?referer=');">JDBC SQL Profiler</a> which will aggregate all of the information and help you decide where you&#8217;ve got slow queries and need indexes.</p>
<p>Mike Hugo has a <a href="http://www.piragua.com/2009/06/17/grails-p6spy-and-sql-profiler/" onclick="pageTracker._trackPageview('/outgoing/www.piragua.com/2009/06/17/grails-p6spy-and-sql-profiler/?referer=');">great post on using the p6spy plugin with the JDBC SQL profiler</a>.</p>
<h4><small>Turn on the MySQL Slow Query Log</small></h4>
<p>If you&#8217;re using a recent version of MySQL, there&#8217;s an easy, built-in way to see which queries are slow and which queries aren&#8217;t using indexes: the <a href="http://dev.mysql.com/doc/refman/5.1/en/slow-query-log.html" onclick="pageTracker._trackPageview('/outgoing/dev.mysql.com/doc/refman/5.1/en/slow-query-log.html?referer=');">slow query log</a>.</p>
<p>To turn it on, you simply need to add a few lines to your mysql cnf file (by default on OSX just create a file at /etc/my.cnf and it will get loaded):</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #66cc66;">&#91;</span>mysqld<span style="color: #66cc66;">&#93;</span>
log<span style="color: #66cc66;">-</span>slow<span style="color: #66cc66;">-</span>queries
<span style="color: #808080; font-style: italic;">#Log all queries &gt; long_query_time seconds, default 10 seconds</span>
long_query_time<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span></pre></div></div>

<p>This will automatically create a log file in your mysql &#8220;data&#8221; directory called <i>host_name</i>-slow.log that contains all queries taking longer than 1 second.</p>
<p>You can optionally add</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">log<span style="color: #66cc66;">-</span>queries<span style="color: #66cc66;">-</span>not<span style="color: #66cc66;">-</span>using<span style="color: #66cc66;">-</span>indexes</pre></div></div>

<p>And this will also log those queries that don&#8217;t have an index (but don&#8217;t take longer than 1 second to execute).  </p>
<p>MySQL also comes with a perl script to parse through the slow log file and show you the number of times each query is slow with some additional statistics.  To run it, you need to add basedir to your my.cnf file.  The basedir value just holds the location of mysql&#8217;s data directory.</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;">basedir<span style="color: #669966;">=</span>/usr/local/mysql</pre></div></div>

<p>Then run the script:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">mysqldumpslow</pre></div></div>

<p>These steps should get you a long way towards figuring out which tables need indexes.</p>
<h4><small>Turn on the MySQL General Query log</small></h4>
<p>MySQL has an additional query log called the <a href="http://dev.mysql.com/doc/refman/5.1/en/query-log.html" onclick="pageTracker._trackPageview('/outgoing/dev.mysql.com/doc/refman/5.1/en/query-log.html?referer=');">general query log</a>.  It logs <i>everything</i> that comes into MySQL and is extremely noisy.  One benefit of it though is that it gives you the full query with all parameters, so it&#8217;s more useful than turning on grails SQL trace log and potentially a little quicker to set up than the p6spy plugin.</p>
<p>You can enable it by putting this in your my.cnf:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">general_log<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span></pre></div></div>

<h4><small>Suggested Reading for MySQL indexes</small></h4>
<p>If you haven&#8217;t created many indexes before, I highly suggest reading <a href="http://www.mysqlperformanceblog.com/2009/09/12/3-ways-mysql-uses-indexes/" onclick="pageTracker._trackPageview('/outgoing/www.mysqlperformanceblog.com/2009/09/12/3-ways-mysql-uses-indexes/?referer=');">this post on indexes on the mysql high performance blog</a>.  The executive summary is that multi-key indexes tailored to your query have a performance edge over individual key indexes on each of the fields.  If you&#8217;re executing a query enough times, it might be worth creating a multi-key index like we have above.</p>
<h3>MySQL Database Engines</h3>
<p>If MySQL is still your performance bottleneck, or if you&#8217;re finding that everything else comes to a stop when you&#8217;re running your batch import, check which storage engine you&#8217;re using.</p>
<p>For grails applications, I&#8217;d prefer InnoDB (or Falcon) to the default MyISAM.  MyISAM is good for read-only situations where you don&#8217;t care about enforced foreign key releationships.  Switching to InnoDB has significantly increased the performance of my app in a number of situations.  InnoDB also supports row level locking, whereas MyISAM will lock the <b>entire table</b> when doing an update or an insert.</p>
<p>If you haven&#8217;t explicitly done anything, chances are that all of your grails-generated tables are MyISAM.  You can change the default storage engine for mysql by specifying a different engine in your my.cnf:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">default<span style="color: #66cc66;">-</span>storage<span style="color: #66cc66;">-</span>engine<span style="color: #66cc66;">=</span>innodb</pre></div></div>

<p>To see the default is for your database execute:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SHOW</span> engines;</pre></div></div>

<p>To see the engine for a particular table, use &#8220;show create table&#8221;:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">SHOW</span> <span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> book\G
<span style="color: #66cc66;">***************************</span> 1<span style="color: #66cc66;">.</span> row <span style="color: #66cc66;">***************************</span>
       <span style="color: #993333; font-weight: bold;">TABLE</span>: book
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span>: <span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`book`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`id`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`version`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`edition`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`isbn`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`title`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MyISAM <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">84192</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>latin1
<span style="color: #cc66cc;">1</span> row <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0.00</span> sec<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>If you need to alter the storage engine for an existing table, you can execute the alter table SQL statement:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> book ENGINE <span style="color: #66cc66;">=</span> INNODB;</pre></div></div>

<h2>Grails Performance Tweaks</h2>
<p>Adding an index and modifying the storage engine of our example book table to InnoDB make our sample app 25-30% faster.  A nice boost from where we were originally, but things are still way too slow:</p>
<p><img src="http://naleid.com/blog/wp-content/uploads/2009/09/performance_with_index.png" alt="Performance with Index" /></p>
<p>Adding indexes to the database drops the database CPU utilization to almost nothing, but grails is still pegged and it still gets much slower over time.  </p>
<p>Something is amiss.</p>
<p>At this point, some people might be inclined to believe the myth that &#8220;grails is slow&#8221; and go through a painful rewrite in another &#8220;faster&#8221; language/technology.  </p>
<p>Don&#8217;t go there yet!  It&#8217;s only slow if you don&#8217;t understand what&#8217;s actually going on under the covers.</p>
<p>After reading through a couple of very <a href="http://burtbeckwith.com/blog/?p=73" onclick="pageTracker._trackPageview('/outgoing/burtbeckwith.com/blog/?p=73&amp;referer=');">helpful</a> <a href="http://burtbeckwith.com/blog/?p=169" onclick="pageTracker._trackPageview('/outgoing/burtbeckwith.com/blog/?p=169&amp;referer=');">posts</a> by Burt Beckwith, and reading through the <a href="http://docs.jboss.org/hibernate/stable/core/reference/en/html/batch.html" onclick="pageTracker._trackPageview('/outgoing/docs.jboss.org/hibernate/stable/core/reference/en/html/batch.html?referer=');">Hibernate chapter on batch processing</a>, we have all of the information we need to speed things up significantly.</p>
<h4><small>Use a Monitoring Tool to Watch Memory/CPU usage Over Time</small></h4>
<p>Because the import gets significantly slower over time, even with the index applied, we know there is some sort of leak.  </p>
<p>If you don&#8217;t have your code instrumented with timing logic already in it, it&#8217;s easy to pop open <code>jconsole</code> or <code>jvisualvm</code> (both already installed and likely in your classpath if you have Java 1.6), connect to your grails instance and watch performance/cpu utilization over time.</p>
<h4><small>The Culprits: Hibernate First-Level Cache and Grails Validation Cache</small></h4>
<p>I <a href="http://burtbeckwith.com/blog/?p=73" onclick="pageTracker._trackPageview('/outgoing/burtbeckwith.com/blog/?p=73&amp;referer=');">found on Burt Beckwith&#8217;s blog</a>, that there are 2 separate leaks, one of them is in the hibernate first-level cache, the other is a map that Grails uses for domain object validation errors.  </p>
<p>Normally, a grails hibernate session executes something quickly and returns.  During importing, we do a ton of processing, all with the same hibernate session.  All of these objects that would normally be garbage collected when the session closed are piling up.</p>
<p>The easiest way to deal with this is to create a simple method to clear out these collections periodically.</p>
<p>We can modify our BookService to clean up GORM after every 100 books we insert:</p>

<div class="wp_syntax"><div class="code"><pre class="groovy" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> BookService <span style="color: #669966;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> sessionFactory
    <span style="color: #000000; font-weight: bold;">def</span> propertyInstanceMap <span style="color: #669966;">=</span> org.<span style="color: #006600;">codehaus</span>.<span style="color: #006600;">groovy</span>.<span style="color: #006600;">grails</span>.<span style="color: #006600;">plugins</span>.<span style="color: #006600;">DomainClassGrailsPlugin</span>.<span style="color: #006600;">PROPERTY_INSTANCE_MAP</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> importBooksInLibrary<span style="color: #669966;">&#40;</span>library<span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        library.<span style="color: #663399;">eachWithIndex</span> <span style="color: #669966;">&#123;</span> <span style="color: #aaaadd; font-weight: bold;">Map</span> bookValueMap, index <span style="color: #669966;">-&gt;</span>
            updateOrInsertBook<span style="color: #669966;">&#40;</span>bookValueMap<span style="color: #669966;">&#41;</span>
            <span style="color: #996600;">if</span> <span style="color: #669966;">&#40;</span>index <span style="color: #669966;">%</span> <span style="color: #cc66cc;">100</span> <span style="color: #669966;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #669966;">&#41;</span> cleanUpGorm<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
        <span style="color: #669966;">&#125;</span>
    <span style="color: #669966;">&#125;</span>    
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> cleanUpGorm<span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">def</span> session <span style="color: #669966;">=</span> sessionFactory.<span style="color: #006600;">currentSession</span>
        session.<span style="color: #006600;">flush</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
        session.<span style="color: #006600;">clear</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
        propertyInstanceMap.<span style="color: #663399;">get</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>.<span style="color: #006600;">clear</span><span style="color: #669966;">&#40;</span><span style="color: #669966;">&#41;</span>
    <span style="color: #669966;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">def</span> updateOrInsertBook<span style="color: #669966;">&#40;</span><span style="color: #aaaadd; font-weight: bold;">Map</span> bookValueMap<span style="color: #669966;">&#41;</span> <span style="color: #669966;">&#123;</span>
        <span style="color: #808080; font-style: italic;">// ... same as above</span>
    <span style="color: #669966;">&#125;</span>
<span style="color: #669966;">&#125;</span></pre></div></div>

<p>This change makes everything much better.  All 100,000 books get inserted in 3 minutes, the same time that it took the naive example to insert the last 1,000 books.</p>
<p><img src="http://naleid.com/blog/wp-content/uploads/2009/09/performance_with_index_and_cleanup.png" alt="Performance with Index and Cleanup" /></p>
<p>Also, because MySQL is now properly using indexes, the load on it is very light.  If we&#8217;re looking for even more speed improvement, this would allow us to split our work up into batches and to make multiple BookService calls (potentially on different web servers).  Because we&#8217;ve switched to using InnoDB, we&#8217;re now working with row-level locking, which isn&#8217;t hostile to this approach unlike MyISAM and it&#8217;s full table locking on Insert/Update.</p>
<h2>Conclusion</h2>
<p>This post is just some of what can be done to improve batch performance with Grails and MySQL.  Using these tips, I was able to speed up my own imports to a level that met the speed requirments for our problem space, but kept our code much more maintainable.  Our domain object remain the canonical code representation of our database model.</p>
<p>There are a number of other things that could be looked at to further speed up batch performance and that could be important to your particular application/infrastructure.</p>
<ul>
<li>connectivity between app server and DB</li>
<li>giving enough memory to your app and DB servers</li>
<li>other load into database and app servers</li>
<li>anemic hardware</li>
<li>poor database design</li>
</ul>
<p>Be sure to weigh the cost of making changes in each of these areas, and run benchmark tests before committing to them.  You&#8217;ll often find that what you think is the bottleneck, isn&#8217;t.   Speed is a feature, but you need to balance it with the costs to achieve it.</p>
<p><script type="text/javascript">var dzone_style = '1';</script><br />
<script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script> </p>
]]></content:encoded>
			<wfw:commentRss>http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>Updated wordpress</title>
		<link>http://naleid.com/blog/2009/09/06/updated-wordpress/</link>
		<comments>http://naleid.com/blog/2009/09/06/updated-wordpress/#comments</comments>
		<pubDate>Sun, 06 Sep 2009 15:38:48 +0000</pubDate>
		<dc:creator>tednaleid</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://naleid.com/blog/?p=62</guid>
		<description><![CDATA[I&#8217;ve just switched hosting providers from slicehost to a reserved EC2 instance.  I also upgraded from a really old version of wordpress to wordpress 2.8.4.  I&#8217;ve been meaning to do this for a while now, but wanting to avoid yesterday&#8217;s worm prompted me to do it this weekend rather than next.
Let me know [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just switched hosting providers from slicehost to a reserved EC2 instance.  I also upgraded from a really old version of wordpress to wordpress 2.8.4.  I&#8217;ve been meaning to do this for a while now, but <a href="http://wordpress.org/development/2009/09/keep-wordpress-secure/" onclick="pageTracker._trackPageview('/outgoing/wordpress.org/development/2009/09/keep-wordpress-secure/?referer=');">wanting to avoid yesterday&#8217;s worm</a> prompted me to do it this weekend rather than next.</p>
<p>Let me know if you see any issues or broken links.</p>
]]></content:encoded>
			<wfw:commentRss>http://naleid.com/blog/2009/09/06/updated-wordpress/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
