<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;D04BRnw7eCp7ImA9WhBaEEU.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091</id><updated>2013-05-20T14:39:17.200-07:00</updated><category term="Refcardz" /><category term="Contegix" /><category term="Pomodoro" /><category term="Uber-Coolness" /><category term="NFSJ" /><category term="DZone" /><category term="zombies" /><category term="Java User Groups" /><category term="Clojure" /><category term="Groovy User Groups" /><category term="Controllers" /><category term="Grails Podcast" /><category term="Terracotta" /><category term="GSP" /><category term="Oracle" /><category term="JavaOne" /><category term="Excuses" /><category term="EJB" /><category term="GORM" /><category term="Scala" /><category term="Grails Books" /><category term="JRuby" /><category term="Agile Community" /><category term="Boeing" /><category term="Posts without links" /><category term="Bloggers" /><category term="Software projects" /><category term="Grails" /><category term="Enterprise Integration" /><category term="Spring" /><category term="Smart People" /><category term="News" /><category term="Griffon" /><category term="Green Bay" /><category term="SDWest" /><category term="Book Review" /><category term="NFJS" /><category term="Webinar" /><category term="Happiness" /><category term="Java" /><category term="Java.next" /><category term="Groovy" /><category term="Blogging" /><category term="Pragmatic Programmers" /><category term="Conferences" /><category term="RegExp" /><category term="Lizard Brains" /><category term="STL" /><category term="Webinar GQuick" /><category term="Linux" /><category term="CapJug" /><category term="Random Thoughts" /><category term="GQuick" /><category term="Speaking" /><title>Kickin' down the cobblestones</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://dave-klein.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>74</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/daveklein" /><feedburner:info uri="daveklein" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>daveklein</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry gd:etag="W/&quot;Ak4NQn08fCp7ImA9WhRQF00.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-6792762888312095218</id><published>2011-12-12T08:32:00.000-08:00</published><updated>2011-12-12T08:56:33.374-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-12T08:56:33.374-08:00</app:edited><title>Grails: A Quick-Start Guide is back</title><content type="html">No, there isn’t a second edition (yet).  But some may have noticed that the ebook of &lt;a href="http://pragprog.com/book/dkgrails/grails"&gt;&lt;em&gt;Grails: A Quick-Start Guide&lt;/em&gt;&lt;/a&gt; (or GQuick) was no longer available on The Pragmatic Programmers’ site.  The thought was that it was becoming obsolete.  But after several requests from developers who are still getting started with the Grails 1.&lt;em&gt;x&lt;/em&gt; framework, the publisher decided to make it available for a while longer.&lt;br /&gt;&lt;br /&gt;Once Grails 2.0 is out and beginning to be widely adopted, GQuick will probably be retired. But for now, it remains one of the best options for developers wanting to quickly take advantage of the powerful Grails framework.&lt;br /&gt;&lt;br /&gt;The publisher is no longer printing copies of GQuick, but if you really want a copy of the dead-tree edition, you can find one on &lt;a href="http://www.amazon.com/product/dp/1934356468/"&gt;Amazon.com&lt;/a&gt;.  (The price seems to be climbing, though.  Currently, &lt;a href="http://www.amazon.com/gp/offer-listing/1934356468/ref=dp_olp_new?ie=UTF8&amp;qid=1323707896&amp;sr=1-4&amp;condition=new"&gt;new copies&lt;/a&gt; are going for $54.39, and &lt;a href="http://www.amazon.com/gp/offer-listing/1934356468/ref=dp_olp_used?ie=UTF8&amp;qid=1323707896&amp;sr=1-4&amp;condition=used"&gt;used copies&lt;/a&gt; for $48.85.)&lt;br /&gt;&lt;br /&gt;For those who have asked, I am working on a Grails 2 intro book (publisher to be determined).  Stay tuned.&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/7dKMWBWxcJA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/6792762888312095218/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=6792762888312095218" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6792762888312095218?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6792762888312095218?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/7dKMWBWxcJA/grails-quick-start-guide-is-back.html" title="Grails: A Quick-Start Guide is back" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2011/12/grails-quick-start-guide-is-back.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkECQX0yeCp7ImA9WhdSEEU.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-6997625284370915803</id><published>2011-07-19T07:13:00.000-07:00</published><updated>2011-07-19T08:17:40.390-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-19T08:17:40.390-07:00</app:edited><title>CocoaConf, And My Anniversary</title><content type="html">For the past few months, my sons and I have been working on a &lt;i&gt;different&lt;/i&gt; kind of project: We are putting on a conference for developers on Apple platforms, such as iPhone, iPad, and Mac. It’s called &lt;a href="http://cocoaconf.com/"&gt;CocoaConf.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The first &lt;a href="http://cocoaconf.com/"&gt;CocoaConf&lt;/a&gt; is being held in Columbus OH, on August 12 - 13, 2011.  We have an exciting line-up of speakers, including &lt;a href="http://dimsumthinking.com/"&gt;Daniel Steinberg&lt;/a&gt;, &lt;a href="http://bill.dudney.net/roller/objc/"&gt;Bill Dudney&lt;/a&gt;, &lt;a href="http://www.subfurther.com/blog/"&gt;Chris Adamson&lt;/a&gt;, &lt;a href="http://juddsolutions.blogspot.com/"&gt;Christopher Judd&lt;/a&gt;, and &lt;a href="http://www.arbormoon.com/"&gt;Dave Koziol&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We will be having three tracks for the two days; this will include an &lt;a href="http://www.cocoaconf.com/session/details/4"&gt;all day hands-on iPhone workshop&lt;/a&gt; on the first day.  It's shaping up to be a very exciting event.&lt;br /&gt;&lt;br /&gt;The idea for this conference came when my #3 son, Solomon, began learning Mac programming using the book &lt;a href="http://pragprog.com/book/tibmac/beginning-mac-programming"&gt;&lt;i&gt;Beginning Mac Programming&lt;/i&gt;&lt;/a&gt; by Tim Isted.  Taking inspiration from my favorite conference series of all time — &lt;a href="http://nofluffjuststuff.com/"&gt;No Fluff, Just Stuff&lt;/a&gt; — we began tossing around ideas.  The NFJS events are known for a capped size so that they don't feel crowded, and for a focus on technical content, without the vendor hype and special events that other conferences tend to have.  So that's what we are doing for &lt;a href="http://cocoaconf.com/"&gt;CocoaConf&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I hadn't blogged about &lt;a href="http://cocoaconf.com/"&gt;CocoaConf&lt;/a&gt; here since it has nothing to do with my usual topics, &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt; and &lt;a href="http://grails.org/"&gt;Grails&lt;/a&gt; (although the CocoaConf site &lt;i&gt;is&lt;/i&gt; being developed in Grails).  But today I am going ahead with this post, so that I have a place to explain a crazy (but fun) idea.&lt;br /&gt;&lt;br /&gt;You see, 26 years ago today, my beautiful wife, Debbie, said “I do.”  And today, we are celebrating this 26th anniversary with &lt;b&gt;a one-day-only &lt;a href="http://cocoaconf.com/"&gt;CocoaConf&lt;/a&gt; discount of 26% off the current early-bird rate of $350&lt;/b&gt;.  That's a $91 savings for today (July 19th) only!  So: If you are interested in developing for the iPhone/iPad or Mac and can make it out to Columbus in August, &lt;b&gt;you can now sign up for CocoaConf for only $259&lt;/b&gt; — but only for today, July 19, 2011.  Just go to &lt;a href="http://cocoaconf.com/register"&gt;http://cocoaconf.com/register&lt;/a&gt; and use the coupon code “ANNIVERSARY”.&lt;br /&gt;&lt;br /&gt;I don't know if anyone will take advantage of this deal, but I thought it would be a fun way to celebrate 26 wonderful years of marriage to my amazing wife.  She is the second best thing God has ever done for me!&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(And finally, I'll leave you with a bit of child exploitation.  Here's our #13, Joshua, telling us where he's headed in August.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-6107af9bb402bb3c" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="//www.youtube.com/get_player"&gt;
&lt;param name="bgcolor" value="#FFFFFF"&gt;
&lt;param name="allowfullscreen" value="true"&gt;
&lt;param name="flashvars" value="flvurl=http://redirector.googlevideo.com/videoplayback?id%3D6107af9bb402bb3c%26itag%3D5%26source%3Dblogger%26app%3Dblogger%26cmo%3Dsensitive_content%253Dyes%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1371234399%26sparams%3Did,itag,source,ip,ipbits,expire%26signature%3D5E6B602BCB042A796A457DB5985C5EC8CF11DC52.7987FDC0C641C957F6080CD975CF9109A086EFB2%26key%3Dck2&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D6107af9bb402bb3c%26offsetms%3D5000%26itag%3Dw160%26sigh%3DmK_pD0CTn_VsXih96AB9kc8qAwA&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;
&lt;embed src="//www.youtube.com/get_player" type="application/x-shockwave-flash"
width="320" height="266" bgcolor="#FFFFFF"
flashvars="flvurl=http://redirector.googlevideo.com/videoplayback?id%3D6107af9bb402bb3c%26itag%3D5%26source%3Dblogger%26app%3Dblogger%26cmo%3Dsensitive_content%253Dyes%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1371234399%26sparams%3Did,itag,source,ip,ipbits,expire%26signature%3D5E6B602BCB042A796A457DB5985C5EC8CF11DC52.7987FDC0C641C957F6080CD975CF9109A086EFB2%26key%3Dck2&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D6107af9bb402bb3c%26offsetms%3D5000%26itag%3Dw160%26sigh%3DmK_pD0CTn_VsXih96AB9kc8qAwA&amp;autoplay=0&amp;ps=blogger"
allowFullScreen="true" /&gt;&lt;/object&gt;
&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/KKkj_YQtqVc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/6997625284370915803/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=6997625284370915803" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6997625284370915803?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6997625284370915803?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/KKkj_YQtqVc/cocoaconf-and-my-anniversary.html" title="CocoaConf, And My Anniversary" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2011/07/cocoaconf-and-my-anniversary.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04NQHwzcSp7ImA9Wx9VEE0.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-297385561285402896</id><published>2011-01-25T12:57:00.000-08:00</published><updated>2011-01-25T18:46:31.289-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-25T18:46:31.289-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Griffon" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy User Groups" /><category scheme="http://www.blogger.com/atom/ns#" term="Java User Groups" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Groovy / Grails User Groups</title><content type="html">Technology user groups benefit both &lt;i&gt;a technology&lt;/i&gt; (with the companies behind it) and &lt;i&gt;its users&lt;/i&gt;.  Java user groups around the world played a big role in the adoption and advance of the Java language and platform.  Even now that Java is in its old age (or on its deathbed, depending on who you talk to), JUGs are actively promoting educational and community-building initiatives.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Groovy community is benefiting similarly from a growing number of user groups.&lt;/b&gt; There are currently a few dozen groups around the world, and more are forming every day.&lt;br /&gt;&lt;br /&gt;Now &lt;b&gt;there is a website that can help you find a group in your area or help you get one started&lt;/b&gt;.  &lt;a href="http://g2groups.net/"&gt;G2Groups.net&lt;/a&gt; has a list of active Groovy user groups, with links to their sites.  If you can't find one in your area, you can propose one.  The site will post a link to your proposal on &lt;a href="http://twitter.com/g2groups"&gt;Twitter&lt;/a&gt;; you can retweet this to help get the word out.  Then when others are interested in your idea, you'll get emailed about it, and you're off and running!&lt;br /&gt;&lt;br /&gt;Once you get a few likeminded (and by "likeminded," I of course mean "brilliant") people together and get a group started, send me a note, and &lt;b&gt;I'll invite you to the &lt;a href="http://groups.google.com/group/gugleaders"&gt;Groovy User Group Leaders&lt;/a&gt; list on Google Groups&lt;/b&gt;.  This list is a great way to get support and ideas from other Groovy/Grails/Griffon/Gaelyk/Gradle/Getc. group leaders.&lt;br /&gt;&lt;br /&gt;I've always said that the best feature of Groovy and Grails is the community.  User groups are a big part of that.  So if you're not already involved in a G2Group, &lt;a href="http://g2groups.net/"&gt;get plugged in&lt;/a&gt;.  You'll be glad you did.&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/9dY1QJ7omQ4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/297385561285402896/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=297385561285402896" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/297385561285402896?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/297385561285402896?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/9dY1QJ7omQ4/groovy-grails-user-groups.html" title="Groovy / Grails User Groups" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>4</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2011/01/groovy-grails-user-groups.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcFR3g4eCp7ImA9Wx5bEUU.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-6817672592529456100</id><published>2010-10-23T15:49:00.000-07:00</published><updated>2010-10-27T06:26:56.630-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-27T06:26:56.630-07:00</app:edited><title>JavaOne Has Been Replaced</title><content type="html">I just got back from &lt;a href="http://www.springone2gx.com/conference/chicago/2010/10/home"&gt;SpringOne/2GX&lt;/a&gt;.  It was an excellent experience.  The enthusiasm and interest level of the attendees was great. The content, both on the Spring side and (of course) the &lt;a href="http://groovy.codehaus.org"&gt;Groovy&lt;/a&gt; and &lt;a href="http://grails.org"&gt;Grails&lt;/a&gt; side, was top-notch.  There were nine tracks loaded with sessions that covered all kinds of topics related to software development in the Java ecosystem.  There were long breaks with plenty of stimulating hallway conversations. Even the keynotes were informative.  At most conferences, I skip the keynotes.  I've become so used to them being just sales pitches from people who don't even use the tools they're talking about.  That wasn't the case here.  One of the highlights of the show was Graeme Rocher's keynote demo of &lt;a href="http://blog.springsource.com/2010/09/07/announcing-gorm-for-redis/"&gt;the new NoSQL DB support in GORM&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;As excellent as it was, I'm not saying that SpringOne/2GX has replaced JavaOne.&lt;br /&gt;&lt;br /&gt;The week before SpringOne/2GX, I took two of my sons to &lt;a href="http://strangeloop2010.com"&gt;the StrangeLoop conference in St. Louis&lt;/a&gt;.  This conference covered several important areas of software development.  There was good coverage of Java and alternate JVM languages and frameworks, along with a bunch of other languages and technologies.  It wasn't held in a big conference center or a nice hotel, but in three different buildings, each with a unique atmosphere.  This &amp;ldquo;small&amp;rdquo; midwest conference featured industry luminaries that you might have expected to see only in the Moscone Center.  To see them &lt;a href="http://www.flickr.com/photos/wondible/5089025865/"&gt;on the stage of a St. Louis night club&lt;/a&gt; was something else!  &lt;br /&gt;&lt;br /&gt;Just this afternoon, after opening registration less than 4 days ago, &lt;a href="http://www.codemash.org/"&gt;the CodeMash conference in Sandusky, OH&lt;/a&gt;, sold out.  This conference, like StrangeLoop, covers a broad range of technologies. Though there is a bit more .NET than I would like to see, :-) it is another excellent event, bringing speakers from across the country and attendees from across the globe.  &lt;br /&gt;&lt;br /&gt;I could go on. There is the &lt;a href="http://www.siliconvalley-codecamp.com/"&gt;Silicon Valley Code Camp&lt;/a&gt;, the &lt;a href="http://www.houstontechfest.com/"&gt;Houston TechFest&lt;/a&gt;, and so many more.  But you get the picture.&lt;br /&gt;&lt;br /&gt;For several years now, JavaOne has been turning into more of a vehicle for pushing a certain technology (&lt;span style="font-style:italic;"&gt;cough&lt;span style="font-weight:bold;"&gt;JavaFX&lt;/span&gt;cough&lt;/span&gt;). The attendance has been gradually dropping.  As developers stopped going to JavaOne, they began to find other events to meet the need that JavaOne was not filling.  Or they started their own.  &lt;br /&gt;&lt;br /&gt;The Oracle acquisition and the subsequent decision to make JavaOne an afterthought to Oracle's annual event didn't help, but JavaOne was already on its way out. It was destroyed the way so many companies are: by &lt;span style="font-weight:bold;"&gt;pushing what it wanted its customers to have&lt;/span&gt; rather than &lt;span style="font-weight:bold;"&gt;providing what its customers wanted&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;So I can't point to a single conference that will be the new JavaOne (although &lt;a href="http://dave-klein.blogspot.com/2010/06/uberconf-exceeding-expectations.html"&gt;Über Conf comes close&lt;/a&gt;). But I &lt;span style="font-style:italic;"&gt;can&lt;/span&gt; look out at all the technical gatherings happening around the world&amp;mdash;&lt;a href="http://www.devoxx.com/display/Devoxx2K10/Home"&gt;Devoxx&lt;/a&gt;, &lt;a href="http://gotocon.com/aarhus-2010/"&gt;JAOO&lt;/a&gt;, &lt;a href="http://www.jaxindia.com/"&gt;the&lt;/a&gt; &lt;a href="http://jaxlondon.com/2010s/"&gt;JAX&lt;/a&gt; &lt;a href="http://jax.de/"&gt;events&lt;/a&gt;, the &lt;a href="http://gr8conf.org/"&gt;GR8 events&lt;/a&gt;, and so many more.  And then I can look closer to home and see all the &amp;ldquo;small&amp;rdquo; conferences that are providing big benefits to attendees and speakers, and I can say it without a doubt. &lt;span style="font-weight:bold;"&gt;JavaOne has been replaced.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/09hJLkPHFOQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/6817672592529456100/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=6817672592529456100" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6817672592529456100?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6817672592529456100?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/09hJLkPHFOQ/javaone-has-been-replaced.html" title="JavaOne Has Been Replaced" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>7</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/10/javaone-has-been-replaced.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04BQnYyeip7ImA9Wx5VFks.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-7606541514050543447</id><published>2010-10-09T10:35:00.000-07:00</published><updated>2010-10-09T15:05:53.892-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-09T15:05:53.892-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Random Thoughts" /><category scheme="http://www.blogger.com/atom/ns#" term="Agile Community" /><title>Move On In Peace</title><content type="html">As long as we measure the success of a movement by adoption numbers, any successful movement will eventually become compromised and diluted.  This is a cycle that has repeated itself time and again.  It happens in all areas of human interaction: politics, religion, science, entertainment, business, and technology, to name a few.&lt;br /&gt;&lt;br /&gt;When this cycle occurs, the founders and early adopters often begin to feel bitter about where things have gone.  They long for the &amp;ldquo;early days.&amp;rdquo; They begin to lash out at the masses that have morphed their creation into something less than what they had in mind.  They may even make a concerted effort to reform the movement, and to bring it back to its roots.  This is understandable, but it is not practical.  I cannot think of a single instance where it has worked.&lt;br /&gt;&lt;br /&gt;I've been thinking of a more sane and peaceful path: Founders and early members of a movement could, at the first sign of success, begin to plan their next move.  Learn from what has been done before. Keep the essence of it, and start over.  If the original idea was good, reuse and rebrand it.  If those unwashed masses did bring a little value after all, borrow it and build on it.  Or scrap the whole mess and reinvent the wheel. (Round does get boring after a while. :) )&lt;br /&gt;&lt;br /&gt;Just be willing to let go of what was, and let those who have come run with it.  Don't whine about it.  Don't attack the newcomers. Just move on. If you miss the &amp;ldquo;good old days,&amp;rdquo; you can always start some new ones.&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/cKZq6QFkRtI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/7606541514050543447/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=7606541514050543447" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/7606541514050543447?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/7606541514050543447?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/cKZq6QFkRtI/move-on-in-peace.html" title="Move On In Peace" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/10/move-on-in-peace.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcMQHw5eSp7ImA9Wx5QEUQ.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-4170853554543277822</id><published>2010-08-30T10:26:00.000-07:00</published><updated>2010-08-30T11:14:41.221-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-30T11:14:41.221-07:00</app:edited><title>GroovyMag Plugin Corner: JavaScript Validation Plugin</title><content type="html">&lt;em&gt;The following post is a reprint of the Plugin Corner article for the April 2009 issue of GroovyMag. You can find this and other past issues at &lt;a href="http://groovymag.com/"&gt;http://groovymag.com&lt;/a&gt;.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Grails provides powerful and easy-to-use constraint validation. With a few short lines in a simple DSL, you can ensure that required fields are filled in or that numeric field values are within a specified range. If you take advantage of Grails’ scaffolding, error reporting is also handled for you. The only catch is that it’s server-side only. If you want this type of validation without a round-trip to the server, you’re on your own — unless you use Peter Delahunty’s brand new &lt;a href="http://grails.org/plugin/javascript-validator"&gt;JavaScript Validation plugin&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Peter released the Javascript Validation plugin earlier in March and then went right to work improving it. At the time of this writing it is at version 0.7 and is working quite well. Let’s see how easy it can be adding client side validation to our Grails applications. We’ll start by installing the plugin:&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;&gt; grails install-plugin javascript-validation&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We’ll need to make a couple changes to the views that we want validation on, but first let’s look at the domain class that we’ll be working with.&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;span class="Apple-style-span"  &gt;&lt;span class="Apple-style-span" style="font-size: 16px; white-space: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;code&gt;&lt;br /&gt;class Book {&lt;br /&gt;   String title&lt;br /&gt;   String author&lt;br /&gt;   Integer pages&lt;br /&gt;   static constraints = {&lt;br /&gt;       title(blank:false)&lt;br /&gt;       author(blank:false)&lt;br /&gt;       pages(range:10..1000)                                                         &lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This simple &lt;code&gt;Book&lt;/code&gt; class (bet you never saw that in an article before) has three constraints. We will use the JavaScript Validation plugin to check those constraints without a trip to the server.&lt;br /&gt;&lt;br /&gt;Open &lt;code&gt;grails-app/views/book/create.gsp&lt;/code&gt; and take a look at the &lt;code&gt;&amp;lt;g:form&amp;gt;&lt;/code&gt; declaration. It should look something like this:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;g:form action=”save” method=”post” &amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The Validation plugin requires that our form contain a &lt;code&gt;name&lt;/code&gt; attribute and an &lt;code&gt;onSubmit&lt;/code&gt; attribute that calls the &lt;code&gt;validateForm&lt;/code&gt; JavaScript function. So, let’s modify our form declaration to look more like this:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;g:form name=”bookCreate”&lt;br /&gt;&lt;br /&gt;        onsubmit=”return validateForm(this);”&lt;br /&gt;&lt;br /&gt;        action=”save” method=”post” &amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally, we need to add the following line to the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of our page:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;jv:generateValidation domain=”book” form=”bookCreate”/&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here we’re just using the minimum required attributes for the &lt;code&gt;&amp;lt;jv:generateValidation&amp;gt;&lt;/code&gt; tag. The &lt;code&gt;domain&lt;/code&gt; attribute takes the domain class name, but with the first letter lowercase. The &lt;code&gt;form&lt;/code&gt; attribute takes the same value that we assigned to the &lt;code&gt;name&lt;/code&gt; attribute of our &lt;code&gt;&amp;lt;g:form&amp;gt;&lt;/code&gt; tag. That’s all it takes to start using this plugin.&lt;br /&gt;&lt;br /&gt;Now if we go to create a new &lt;code&gt;Book&lt;/code&gt; and leave out the author’s name for some dumb reason, we’ll see something like the screenshot in Figure 1.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Mt9WQBouLcM/THvzVXksXnI/AAAAAAAAAPI/DtM6yYEzqis/s1600/img1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px; height: 171px;" src="http://3.bp.blogspot.com/_Mt9WQBouLcM/THvzVXksXnI/AAAAAAAAAPI/DtM6yYEzqis/s200/img1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5511266117448654450" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Not bad for a couple lines of code. That’s just the basics. The &lt;code&gt;&amp;lt;jv:generateValidation&amp;gt;&lt;/code&gt; tag has ten more attributes that we can use to add more vigor and vim to our validations.&lt;br /&gt;&lt;br /&gt;There is support for both domain classes and command objects. Errors can be displayed in a JavaScript alert (as shown in Figure 1), which is the default, or they can be shown in a list placed in a page element of our choosing, or we can even create custom error handling.&lt;br /&gt;&lt;br /&gt;Currently only the following constraints are supported by the plugin:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;blank&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;nullable&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;email&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;creditCard&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;matches&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;range&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;This list is considerably shorter than the list of constraints that Grails provides, but as we can see by the 6 updates since its creation a few weeks ago, this plugin is being actively enhanced, so I wouldn’t be surprised to see more constraints supported soon.&lt;br /&gt;&lt;br /&gt;Oh, and lest I forget, the Javascript Validation plugin works with Grails internationalization. So with a minor tweak to our &lt;code&gt;messages.properties&lt;/code&gt; file, we can customize our error messages as shown in Figure 2.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Mt9WQBouLcM/THvzfzf_7TI/AAAAAAAAAPQ/qo8Us4z85t4/s1600/img2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px; height: 175px;" src="http://4.bp.blogspot.com/_Mt9WQBouLcM/THvzfzf_7TI/AAAAAAAAAPQ/qo8Us4z85t4/s200/img2.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5511266296743849266" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This plugin has great potential. It will already save significant development time in setting up client-side validation, and I’m sure it’s going to keep getting better. Stop by the Grails Plugin Portal and check it out. You can leave a comment with enhancement suggestions, or, if you’ve tried it out, let others know what you think with a rating. I’m giving it 5 stars!&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Resources&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Grails Plugin Portal page:&lt;br /&gt;&lt;a href="http://grails.org/plugin/javascript-validator"&gt;http://grails.org/plugin/javascript-validator&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Peter Delahunty’s Blog:&lt;br /&gt;&lt;a href="http://blog.peterdelahunty.com/"&gt;http://blog.peterdelahunty.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/zAqYmNeyBdE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/4170853554543277822/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=4170853554543277822" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/4170853554543277822?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/4170853554543277822?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/zAqYmNeyBdE/javascript-validation-plugin.html" title="GroovyMag Plugin Corner: JavaScript Validation Plugin" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_Mt9WQBouLcM/THvzVXksXnI/AAAAAAAAAPI/DtM6yYEzqis/s72-c/img1.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/08/javascript-validation-plugin.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcAQn4_eyp7ImA9WxFVFk8.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-5188012008877247849</id><published>2010-06-15T10:17:00.000-07:00</published><updated>2010-06-15T10:47:23.043-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-15T10:47:23.043-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="NFJS" /><category scheme="http://www.blogger.com/atom/ns#" term="Uber-Coolness" /><category scheme="http://www.blogger.com/atom/ns#" term="Conferences" /><title>ÜberConf - Exceeding Expectations</title><content type="html">ÜberConf kicked off yesterday with the pre-conference iPhone/iPad workshop.  The workshop was completely full, with just over 90 people. The view from the front of the room was pretty impressive -- all those glowing apples.  ;-)&lt;br /&gt;&lt;br /&gt;Later, the conference proper got going with a great dinner and a keynote by industry luminary Cliff Click. At the time when a normal No Fluff, Just Stuff event would wrap up for the day, there was an opening reception with more food and drinks and a roving magician.  A great time was had by all.&lt;br /&gt;&lt;br /&gt;This morning, the sessions are going in full swing.  I'm actually skipping one right now to finish up my sample project for the Grails workshop tomorrow.  But the rest of the week is packed with great technical sessions, and not a marketing person in sight!&lt;br /&gt;&lt;br /&gt;I caught Keith Donald's Spring MVC session this morning and plan on making it to a session by Ted Neward this afternoon.  The content choices are amazing. You've got Java Collections, Functional Java, Groovy, Grails, Wicket, Camel, Hadoop, NoSQL, Agile Architecture, JRuby, TDD, and on and on.  In fact, it's hard to think of a buzz word in the Java ecosystem that isn't covered here.&lt;br /&gt;&lt;br /&gt;And the attendees are the best part.  I've met folks from all over the country and beyond.  I even ran into members of CapJUG and the &lt;a href="http://www.meetup.com/GatewayGroovyUsers/"&gt;Gateway Groovy Users&lt;/a&gt;.  Seeing so many old friends and meeting so many new ones is definitely the best part of a conference like this.  And with the longer breaks, receptions, etc., you actually get time to visit with folks without missing the tech sessions.&lt;br /&gt;&lt;br /&gt;With all due respect to the many great folks who make the pilgrimage to San Francisco every year, this is what JavaOne should have been.&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/5TsY99aFZJI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/5188012008877247849/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=5188012008877247849" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/5188012008877247849?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/5188012008877247849?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/5TsY99aFZJI/uberconf-exceeding-expectations.html" title="ÜberConf - Exceeding Expectations" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/06/uberconf-exceeding-expectations.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UCRXoyfSp7ImA9WxFQFks.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-1351895999256358845</id><published>2010-05-12T03:34:00.000-07:00</published><updated>2010-05-12T03:47:44.495-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-12T03:47:44.495-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Webinar GQuick" /><category scheme="http://www.blogger.com/atom/ns#" term="Terracotta" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Recording of Grails / Terracotta webinar</title><content type="html">In case you missed it and in case you're interested, Terracotta has posted a recording of the webinar that Mike Allen and I held a couple weeks ago. You can catch it in all of its glory (or lack thereof :) at &lt;a href="http://bit.ly/scaling_grails"&gt;http://bit.ly/scaling_grails&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;During the demo I mentioned a blog post coming to the &lt;a href="http://gquick.blogspot.com"&gt;GQuick blog&lt;/a&gt; where we would add &lt;a href="http://www.quartz-scheduler.org/"&gt;Quartz scheduling&lt;/a&gt; to TekDays (the sample app from &lt;a href="http://tinyurl.com/grails-quick-start"&gt;GQuick&lt;/a&gt;), well that post ended up &lt;a href="http://dave-klein.blogspot.com/2010/05/quartz-and-grails.html"&gt;here&lt;/a&gt; instead. &lt;br /&gt;&lt;br /&gt;Once again I'd like to thank the folks at &lt;a href="http://terracotta.org/"&gt;Terracotta&lt;/a&gt; for their cool technology and for their support of the Grails community.&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/EnmYbs0muPw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/1351895999256358845/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=1351895999256358845" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/1351895999256358845?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/1351895999256358845?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/EnmYbs0muPw/recording-of-grails-terracotta-webinar.html" title="Recording of Grails / Terracotta webinar" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/05/recording-of-grails-terracotta-webinar.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UAQ304eyp7ImA9WxFQEE0.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-3527361682515512674</id><published>2010-05-04T13:33:00.001-07:00</published><updated>2010-05-04T13:34:02.333-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-04T13:34:02.333-07:00</app:edited><title>Quartz and Grails: A Quick-Start Guide</title><content type="html">&lt;p&gt;Terracotta's Quartz scheduler has always played a key role in Grails development.  Originally it was built into the framework; now it is a core plugin.  Quartz allows us to have code executed at regular intervals.  This a great way to have batch processes or system checks performed at off hours.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The Quartz plugin provides three different mechanisms (triggers) to determine the timing of job execution: Simple, Cron, and Custom.  With a simple trigger, we can set the amount of time to wait before initial job execution, an interval to wait between repeated executions, and the number of times the job should be executed.  The cron trigger also allows us to set a start delay. Then it takes a cron expression, which we can use to set a wide range of schedules.  With a custom trigger – well, you can use your imagination.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In our TekDays application, we have lists of tasks that need to be done to organize a technical event.  These tasks have due dates, but we currently have no way of reminding event organizers and volunteers when they have tasks that are overdue.  That's where Quartz comes in.  In this post, we'll create a Quartz job to check for overdue tasks and send a reminder email to the person assigned to that task.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;First, we'll install the Quartz plugin:&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;&gt; grails install-plugin quartz&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The plugin provides us with a new Grails script, &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;create-job&lt;/span&gt;.  We'll use this script to create our &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;TaskReminderJob&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;&gt; grails create-job TaskReminder&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The create-job script will create a stubbed out &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;TaskReminderJob.groovy&lt;/span&gt; that looks like this:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;class TaskReminderJob {&lt;br /&gt;   def timeout = 5000l // execute job once in 5 seconds&lt;br /&gt;&lt;br /&gt;   def execute() {&lt;br /&gt;       // execute task&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;We'll replace the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;timeout&lt;/span&gt; property with a triggers closure in a moment, but first let's look at the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;execute&lt;/span&gt; method.  This method will be called at the intervals that we determine with the triggers.  We can put any code we want in this method, but the most common practice, and the one we'll follow, is to call a method of a service class.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For triggering the call to our service method we'll use the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;cron&lt;/span&gt; expression: &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;"0 0 2 ? * MON-FRI"&lt;/span&gt;, which will execute every weekday at 2:00AM.  This is how our new &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;TaskReminderJob&lt;/span&gt; looks:&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;class TaskReminderJob {&lt;br /&gt;   def taskService&lt;br /&gt;   static triggers = {&lt;br /&gt;       cron name: 'cronTrigger', cronExpression: "0 0 2 ? * MON-FRI"&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   def execute() {&lt;br /&gt;       taskService.sendTaskReminders()&lt;br /&gt;       log.info("Task reminders sent on ${new Date()}")&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now we need to add the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;sendTaskReminders()&lt;/span&gt; method to our &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;TaskService&lt;/span&gt;.  This method will use the Mail plugin (which you can find more about at &lt;a href="http://grails.org/plugin/mail/"&gt;http://grails.org/plugin/mail&lt;/a&gt;), so we'll add that to &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;TaskService&lt;/span&gt; too.  Something like this:&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;class TaskService {&lt;br /&gt;   def mailService&lt;br /&gt;&lt;br /&gt;   //...&lt;br /&gt;&lt;br /&gt;   def sendTaskReminders(){&lt;br /&gt;       def tasks = Task.findAllByDueDateLessThan(new Date())&lt;br /&gt;       tasks.each{task -&gt;&lt;br /&gt;           def recipient&lt;br /&gt;           if (task.assignedTo)&lt;br /&gt;               recipient task.assignedTo.email&lt;br /&gt;           else&lt;br /&gt;               task.event.organizer.email&lt;br /&gt;   &lt;br /&gt;           mailService.sendMail {&lt;br /&gt;       to recipient&lt;br /&gt;       from "admin@tekdays.com"&lt;br /&gt;       subject "Task Reminder"&lt;br /&gt;       body """The following task is overdue:&lt;br /&gt;      ${task.title}"""&lt;br /&gt;           }    &lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;That's all there is to it.  We now have the confidence of knowing that event organizers and volunteers will be kept informed of the tasks they need to do.  And based on the experience of some people I know who recently put on a tech conference, this is important.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now, something that in days past might have required us developers to climb tall mountains to make supplication to sysadmins wearing robes and conical hats has been made almost trivial by Quartz and the Quartz plugin.  I, for one, am impressed and grateful.  (I'm getting way too old for mountain climbing.)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;But wait (as they say) – there's more.  As TekDays gets more and more traffic (which we know will happen with all the new and exciting technologies coming out these days), we will want to take advantage of the power of Terracotta and cluster our Quartz jobs.  To do this, we just need to create the property file: &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;grails-app/conf/quartz.properties.&lt;/span&gt;  Then enter the following values in this file:&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;org.quartz.jobStore.class = org.terracotta.quartz.TerracottaJobStore&lt;br /&gt;org.quartz.jobStore.tcConfigUrl = localhost:9510&lt;br /&gt;org.quartz.scheduler.instanceName = TekDaysScheduler&lt;br /&gt;org.quartz.scheduler.instanceId = AUTO&lt;br /&gt;org.quartz.scheduler.jmx.export = true&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Finally, we'll copy &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;quartz-terracotta-1.1.0.jar&lt;/span&gt; in our &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;lib&lt;/span&gt; folder.   The &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;quartz-terracotta&lt;/span&gt; jar comes in the Terracotta download, which can be found at &lt;a href="http://www.terracotta.org/dl/oss-download-catalog"&gt;http://www.terracotta.org/dl/oss-download-catalog&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now, if we've clustered our TekDays application as described in &lt;a href="http://gquick.blogspot.com/2010/03/clustering-grails-app-with-terracotta.html"&gt;an earlier post&lt;/a&gt;, our scheduled jobs will be spread out across all the nodes.  Not too shabby.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;There is still some room for improvement in the Grails / Terracotta integration story, but I continue to be amazed at just how low the barrier of entry is to these powerful products.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/hxMm1rXja2k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/3527361682515512674/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=3527361682515512674" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/3527361682515512674?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/3527361682515512674?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/hxMm1rXja2k/quartz-and-grails.html" title="Quartz and Grails: A Quick-Start Guide" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>3</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/05/quartz-and-grails.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcNQns4cCp7ImA9WxFRE0s.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-3135067376878396067</id><published>2010-04-26T17:09:00.000-07:00</published><updated>2010-04-27T04:18:13.538-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-27T04:18:13.538-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Webinar" /><category scheme="http://www.blogger.com/atom/ns#" term="Terracotta" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Like speaking at a conference in my bath robe</title><content type="html">On April 27th at 11:00am Pacific time, Mike Allen and I will be holding a free webinar on clustering and scaling grails applications the easy way.  A webinar is a cool thing.  It's like a tech conference session where you can't see anybody.  So, while you're sitting at your desk at work or at home or in a coffee shop, Mike will be in California somewhere and I'll be sitting in my basement office in St. Louis, quite possibly still in my pajamas.  &lt;br /&gt;&lt;br /&gt;But that's not the important part.  The important part is that we'll be talking about how easy it is to make a Grails application scalable.  To demonstrate that we'll be using one of my favorite sample apps, TekDays from &lt;a href="http://tinyurl.com/grails-quick-start"&gt;Grails: A Quick-Start Guide&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;If you haven't already, go ahead and sign up at &lt;a href="http://bit.ly/aeDQ3I"&gt;http://bit.ly/aeDQ3I&lt;/a&gt;.  The whole thing will be recorded and posted later.  So, if you can't make it on the 27th or if 11am Pacific is the middle of the night for you, register anyway so you can be notified when the recording is available.&lt;br /&gt;&lt;br /&gt;If you can make it though, it would be great to have you.  &lt;br /&gt;&lt;br /&gt;See you there (in a figurative sense),&lt;br /&gt;Dave&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/qO2TKNbzZwA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/3135067376878396067/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=3135067376878396067" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/3135067376878396067?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/3135067376878396067?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/qO2TKNbzZwA/like-speaking-at-conference-in-my-bath.html" title="Like speaking at a conference in my bath robe" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/04/like-speaking-at-conference-in-my-bath.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UASXg7eip7ImA9WxFTF0g.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-1966006009539136319</id><published>2010-04-07T19:29:00.000-07:00</published><updated>2010-04-08T11:27:28.602-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-08T11:27:28.602-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Scala" /><category scheme="http://www.blogger.com/atom/ns#" term="JRuby" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="NFJS" /><category scheme="http://www.blogger.com/atom/ns#" term="Conferences" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Clojure" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>ÜberConf</title><content type="html">I am very excited about the upcoming &lt;a href="http://uberconf.com/"&gt;ÜberConf&lt;/a&gt; - June 14 - 17, Denver, CO.  Even before I found out that I'd be speaking at it, I was planning to attend.  I've been to a lot of conferences, and I think this is going to be the best one ever!&lt;br /&gt;&lt;br /&gt;I've been attending technical conferences for over 15 years.  I've been to big ones and small ones, free ones and expensive ones.  Just doing a quick count in my head, I think I've been to around 35 tech events.  Most of these have been as an attendee and on my own dime, because I am convinced of their usefulness and value.  More recently I've been speaking at some conferences.  Over the years I've become somewhat of a tech conference connoisseur.  &lt;br /&gt;&lt;br /&gt;Of all these events, the best have been the ones put on by Jay Zimmerman of &lt;a href="http://nofluffjuststuff.com/"&gt;No Fluff, Just Stuff&lt;/a&gt; fame.  The NFJS events and others, such as the Groovy/Grails Experience, the Agile IT Experience and SpringOne/2GX, have some elements that other conference organizers just can't seem to duplicate.  &lt;a href="http://codemash.org/"&gt;CodeMash&lt;/a&gt; comes close, and the old Borland Developer Conferences were also pretty good, but neither of these are quite up to the level of an NFJS event.  &lt;br /&gt;&lt;br /&gt;JavaOne used to score real high on the technical content before it became JavaFX One, but the conference organization and overall experience was always lacking.  The SD conferences usually had some big names that were worth the price of admission, but the rest of the sessions were hit and miss, and the mobs that were there just for the free expo floor made it so difficult to get to sessions that it often wasn't worth it.&lt;br /&gt;&lt;br /&gt;The NFJS events have speakers who are well known, though maybe not as famous as some of the SD headliners. More importantly, they know their stuff, and they have tons of experience in presenting it to others.  And since the event size is purposely kept small, it's easy to get to the sessions of interest and easy to get time to talk with the speakers.  The schedule is always arranged with plenty of break time for the hallway discussions and questions after the sessions.  And all of the little details that we don't really notice but that provide for a much better learning experience are taken care of.&lt;br /&gt;&lt;br /&gt;But back to ÜberConf.  This event will, I'm sure, have the quality experience and flawless execution common to all NFJS events, but with an expanded focus, expanded schedule and an amazing line-up of speakers (and me too :).&lt;br /&gt;&lt;br /&gt;ÜberConf's technical content will be what JavaOne should have been over the last couple years.  It will fully embrace Java the platform, with sessions on Java, Groovy, JRuby, Clojure and Scala.  ÜberConf goes beyond just the languages and draws from the rich diversity of open source communities that have found a home on the JVM, with &lt;a href="http://grails.org/"&gt;Grails&lt;/a&gt;, &lt;a href="http://wicket.apache.org/"&gt;Wicket&lt;/a&gt;, &lt;a href="http://gradle.org/"&gt;Gradle&lt;/a&gt;, &lt;a href="http://maven.apache.org/"&gt;Maven&lt;/a&gt;, &lt;a href="http://gaelyk.appspot.com/"&gt;Gaelyk&lt;/a&gt;, &lt;a href="http://camel.apache.org/"&gt;Camel&lt;/a&gt;, and more.  And since what we're developing with is only part of the story, ÜberConf goes on to bring together some of most important ideas in agile processes from speakers such as &lt;a href="http://www.estherderby.com/"&gt;Esther Derby&lt;/a&gt;, &lt;a href="http://www.jrothman.com/"&gt;Johanna Rothman&lt;/a&gt;, &lt;a href="http://www.devjam.com/"&gt;David Hussman&lt;/a&gt;, &lt;a href="http://www.michaelnygard.com/"&gt;Michael Nygard&lt;/a&gt;, and others.&lt;br /&gt;&lt;br /&gt;With a mix of 90 minute sessions and 3 hour workshops, and eight concurrent tracks to choose from, ÜberConf will be packed with great content.  With attendance capped at 500, it will be easy to get time to talk with speakers and other attendees - and getting to and from the sessions will be easy.&lt;br /&gt;&lt;br /&gt;I speak from experience when I say that you will leave this conference full of new ideas and inspiration.  Check out &lt;a href="http://uberconf.com/conference/denver/2010/06/schedule_at_a_glance"&gt;the schedule&lt;/a&gt;.  You'll find plenty of sessions that apply to your current work, but don't stop there.  To get the most out of an event like this, you need to go to sessions about topics you know nothing about.  You will be amazed at how much you can learn about what you are currently doing by learning about new tools and technologies.&lt;br /&gt;&lt;br /&gt;Check out &lt;a href="http://uberconf.com/"&gt;the site&lt;/a&gt; for details.  There's much more than I've discussed here, including sessions on iPhone, iPad and Android development.  For what's included, the full registration price is a steal, but if you register by Monday, April 12th, there's a big discount.  So register now, or register later, but do register and attend this awesome conference.  &lt;br /&gt;&lt;br /&gt;See you there!&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/1MsFuYwwXEU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/1966006009539136319/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=1966006009539136319" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/1966006009539136319?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/1966006009539136319?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/1MsFuYwwXEU/uberconf.html" title="ÜberConf" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/04/uberconf.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUNSHs6eCp7ImA9WxBaF0w.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-6961209874605233442</id><published>2010-03-27T10:33:00.000-07:00</published><updated>2010-03-27T10:51:39.510-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-27T10:51:39.510-07:00</app:edited><title>Hats Off to Terracotta</title><content type="html">&lt;p style="margin-bottom: 0in"&gt;One of the advantages of Grails is the way that it gives us access to the wealth of proven frameworks in the Java ecosystem.  There are Java frameworks and libraries to help with every aspect of application development you could imagine.  For many applications, a major requirement that the Java world has worked out quite well is scalability.  And when we think of Java and scalability we naturally think of &lt;a href="http://terracotta.org/"&gt;Terracotta&lt;/a&gt;.&lt;/p&gt;&lt;p style="margin-bottom: 0in"&gt;Of all the open source libraries and frameworks available in the Java ecosystem, Terracotta is one of the most Grails-friendly.  In fact, one of Terracotta's projects is built right into Grails (EhCache). Another is one of the most popular Grails plugins (Quartz).  What's really cool is that as an organization, Terracotta sees the important role that Grails is playing the Java development space, and is actively working to make their products integrate better with Grails.&lt;/p&gt;&lt;p style="margin-bottom: 0in"&gt;Recently, I undertook the task of trying this integration out with the sample app from my book, &lt;a href="http://pragprog.com/titles/dkgrails/grails"&gt;Grails: A Quick-Start Guide&lt;/a&gt;.  Other than Quartz, I hadn't used any of their products before, so I was a bit intimidated, but I was pleasantly surprised with how easy it is.  As with any tool, you can get into more advanced usages that may take more configuration and more work.  But the basic integration was a snap!&lt;/p&gt;&lt;p style="margin-bottom: 0in"&gt;I've put up &lt;a href="http://gquick.blogspot.com/2010/03/clustering-grails-app-with-terracotta.html"&gt;the first of a series of blog posts&lt;/a&gt; on the GQuick blog, detailing the steps needed to integrate Terracotta's Web Sessions Express clustering tool with the TekDays application from the book.  Future posts will cover some of the other products in the Terracotta family.&lt;/p&gt;&lt;p style="margin-bottom: 0in"&gt;If you're a Grails developer and haven't taken a look at Terracotta, check 'em out at &lt;a href="http://terracotta.org/"&gt;http://terracotta.org&lt;/a&gt;.&lt;/p&gt;&lt;p style="margin-bottom: 0in"&gt;Also check out these resources by others in the Grails community who have discovered the synergy of Terracotta and Grails:&lt;/p&gt;&lt;p style="margin-bottom: 0in"&gt;&lt;a href="http://adhockery.blogspot.com/2010/02/full-page-caching-in-grails-with.html"&gt;http://adhockery.blogspot.com/2010/02/full-page-caching-in-grails-with.html&lt;/a&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;a href="http://burtbeckwith.com/blog/?p=244"&gt;http://burtbeckwith.com/blog/?p=244&lt;/a&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;a href="http://ehcache.org/documentation/grails.html"&gt;http://ehcache.org/documentation/grails.html&lt;/a&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;a href="http://adhockery.blogspot.com/2010/02/full-page-caching-in-grails-with.html"&gt;http://alterlabs.com/technologies/java/terracotta-plugin-for-grails/&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/21LbCoNRwOM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/6961209874605233442/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=6961209874605233442" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6961209874605233442?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6961209874605233442?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/21LbCoNRwOM/hats-off-to-terracotta.html" title="Hats Off to Terracotta" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>2</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/03/hats-off-to-terracotta.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEDQnozeip7ImA9WxBUGEw.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-4855041582150931177</id><published>2010-03-05T09:02:00.000-08:00</published><updated>2010-03-05T09:37:53.482-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-05T09:37:53.482-08:00</app:edited><title>GroovyMag Plugin Corner: Grails Help-Balloon Plugin</title><content type="html">&lt;em&gt;The following post is a reprint of the Plugin Corner article for the January 2009 issue of GroovyMag. You can find this and other past issues at &lt;a href="http://groovymag.com/"&gt;http://groovymag.com&lt;/a&gt;.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Sometimes our web applications get a little more complex and not entirely intuitive. When this happens, it is important to find ways to provide the cues and clues that our users need to find their way around and to accomplish the task at hand. The Help-Balloon plugin can help with that.&lt;br /&gt;&lt;br /&gt;The Help-Balloon plugin provides a pair of tags which will render an icon in your view. This icon is a link which brings up a balloon shaped, non-modal dialog with the text that you give it. It’s simple, but very handy. Let’s see how we can add this helpful gadget to our toolbox.&lt;br /&gt;&lt;br /&gt;First things first. Make sure that you are in your project’s root directory, and then run the following command:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;grails install-plugin Help-Balloon&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The next step is to add the &lt;code&gt;&amp;lt;g:helpBalloon&amp;gt;&lt;/code&gt; tag to the head of our &lt;code&gt;.gsp&lt;/code&gt; page. For our example we will start with our List view. Here’s the head section of our &lt;code&gt;list.gsp&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;meta http-equiv="Content-Type"&lt;br /&gt;&lt;br /&gt;content="text/html; charset=UTF-8"/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;meta name="layout" content="main" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;g:helpBalloons /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;title&amp;gt;Book List&amp;lt;/title&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;&amp;lt;g:helpBalloon&amp;gt;&lt;/code&gt; tag will load the Prototype Javascript library (if it isn’t already loaded). By default it will find this library in your Grails installation. If you have a different location for Prototype, you can declare that with the base attribute. We’ll take a look at some other customizations that are possible with this tag shortly. For now, let’s add a help balloon to our list view.&lt;br /&gt;&lt;br /&gt;In our &lt;code&gt;list.gsp&lt;/code&gt; we will add another &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; to our table. If all goes well, this will give us an icon at the end of each row in our list table.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;td&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;g:helpBalloon title="Book Info"&lt;br /&gt;&lt;br /&gt;content="${bookInstance.moreInfo()}"/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/td&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see, the &lt;code&gt;&amp;lt;g:helpBalloon&amp;gt;&lt;/code&gt; tag has &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt; attributes. The &lt;code&gt;title&lt;/code&gt; will show up as a heading in the balloon and you can probably guess what the &lt;code&gt;content&lt;/code&gt; ends up as. For static&lt;br /&gt;text from a message bundle, you can also use the &lt;code&gt;code&lt;/code&gt; attribute. In our example the balloon content will be the same as the fields in the table but in a paragraph format. The content can be HTML so &lt;code&gt;&amp;lt;br /&amp;gt;&lt;/code&gt; tags are an easy way to structure the text for our balloon, but if we put them in the tag it doesn’t work. For example:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;g:helpBallon title="Foo" content="line1&amp;lt;br/&lt;br /&gt;&lt;br /&gt;&amp;gt;line2&amp;lt;br/&amp;gt;line3" /&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;will leave the content of the balloon empty. (At least that’s what happened to me.) However those same break tags passed in as the result of a method work fine. So, we added a &lt;code&gt;moreInfo()&lt;/code&gt; method to our &lt;code&gt;Book&lt;/code&gt; class to give us the text we want. This has a nice side-effect of keeping our page cleaner.&lt;br /&gt;&lt;br /&gt;For the curious here’s the code for the &lt;code&gt;moreInfo()&lt;/code&gt; method:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;String moreInfo(){&lt;br /&gt;  """$title &amp;lt;br/&amp;gt;&lt;br /&gt;  by $author&amp;lt;br/&amp;gt;&lt;br /&gt;  published in $published&amp;lt;br/&amp;gt;&lt;br /&gt;  pg: $pages / ISBN: $isbn """&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When we run our application we get something like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Mt9WQBouLcM/S5FBC6KxmtI/AAAAAAAAANM/vfRF7X7xJPg/s1600-h/help-book-list.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px; height: 84px;" src="http://4.bp.blogspot.com/_Mt9WQBouLcM/S5FBC6KxmtI/AAAAAAAAANM/vfRF7X7xJPg/s200/help-book-list.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5445204942697634514" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And when we click on one of those icons, the balloon will show&lt;br /&gt;up:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Mt9WQBouLcM/S5FBPmSrumI/AAAAAAAAANU/J6OkvHQRaEg/s1600-h/help-balloon.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px; height: 154px;" src="http://1.bp.blogspot.com/_Mt9WQBouLcM/S5FBPmSrumI/AAAAAAAAANU/J6OkvHQRaEg/s200/help-balloon.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5445205160700394082" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That’s about all there is to using the Help-Balloon plugin - except that I promised to show how we can customize a couple more things with the &lt;code&gt;&amp;lt;g:helpBalloon&amp;gt;&lt;/code&gt; tag that goes in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of our page. This tag &lt;strong&gt;can has&lt;/strong&gt; optional &lt;code&gt;button&lt;/code&gt; and &lt;code&gt;icon&lt;/code&gt; attributes (it can has cheezburgr, too). &lt;em&gt;[After seeing this typo, I couldn't resist. -- Ed.]&lt;/em&gt; Both of these take a path to an image. If you specify an icon it will replace the "letter i" icon that is used for the link. The button attribute is used to replace the "x" in the upper right corner of the balloon.&lt;br /&gt;&lt;br /&gt;The Help-Balloon plugin is based on the HelpBalloon system written by Beau Scott. You can find more detailed documentation and keep up with the latest updates of the Javascript code on his&lt;br /&gt;site (see references).&lt;br /&gt;&lt;br /&gt;There you have it: a Grails-easy way to add help balloons to your applications. I bet you can think of dozens of ways to use help balloons. Well, at least two or three. In any case, your toolbox just got a little more powerful.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;br /&gt;Help-Balloon Plugin page:&lt;br /&gt;&lt;a href="http://grails.org/plugin/help-balloons"&gt;&lt;br /&gt;http://grails.org/plugin/help-balloons&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;Beau Scott’s web site:&lt;br /&gt;&lt;a href="http://www.beauscott.com/"&gt;&lt;br /&gt;http://www.beauscott.com/&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/181ahyxET2o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/4855041582150931177/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=4855041582150931177" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/4855041582150931177?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/4855041582150931177?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/181ahyxET2o/help-balloon-plugin.html" title="GroovyMag Plugin Corner: Grails Help-Balloon Plugin" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_Mt9WQBouLcM/S5FBC6KxmtI/AAAAAAAAANM/vfRF7X7xJPg/s72-c/help-book-list.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/03/help-balloon-plugin.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0AGRXoyfyp7ImA9WxBWF08.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-5291480775664856929</id><published>2010-02-09T07:05:00.000-08:00</published><updated>2010-02-09T07:35:24.497-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-09T07:35:24.497-08:00</app:edited><title>Grails: It Just Makes Sense</title><content type="html">&lt;p&gt;Grails. &lt;i&gt;It just makes sense.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;After a recent &lt;a href="http://www.meetup.com/GatewayGroovyUsers/"&gt;Gateway Groovy Users&lt;/a&gt; meeting, some of us were talking about the adoption of &lt;a href="http://grails.org/"&gt;Grails&lt;/a&gt;, which is still on the rise.  The signs are everywhere: the &lt;a href="http://g2groups.net/proposed"&gt;increasing number&lt;/a&gt; and &lt;a href="http://dave-klein.blogspot.com/2010/01/groovy-and-grails-in-gateway-city.html"&gt;turnout&lt;/a&gt; of &lt;a href="http://g2groups.net/"&gt;Groovy user groups&lt;/a&gt;, the number of openings on various job sites, the increasing number of Java frameworks that are including Groovy support.&lt;/p&gt;&lt;p&gt;This led to another question.  Why do individuals and companies still say things like “&lt;i&gt;We can't use Grails because we are a Java shop&lt;/i&gt;”?  Do “Java shops” use Spring?  Spring beans can be written in Groovy.  Do “Java shops” use JSF?  JSF backing beans can be written in Groovy.  Contrariwise, most Grails artifacts can be written in Java.  Grails is a Java framework, just like Spring, JSF, etc.  It just happens to be the first one out with Groovy support – and the best Groovy support, at that.&lt;/p&gt;&lt;p&gt;Consider that Grails uses Groovy for some things for which other Java frameworks use another non-Java language – one that is much further from Java in syntax and usage than Groovy.  XML is not Java.  XML does not compile to Java byte-code.  Grails allows you to use Groovy for many of the things for which other frameworks require (or used to require) you to use XML.  Now some other Java frameworks are providing support for Groovy in configuration files, instead of XML.  So the differences continue to blur.&lt;/p&gt;&lt;p&gt;More and more developers are seeing the value of Groovy, and consequently tools like Grails and Griffon.  You can see this in various polls around the internet, some of which we've discussed in &lt;a href="http://dave-klein.blogspot.com/2009/03/thoughts-on-groovy-grails-griffon-and.html"&gt;a previous blog post&lt;/a&gt;.  Now there is hope that more decision makers will get a clue.  In &lt;a href="http://www.forbes.com/2010/02/02/computer-programming-java-technology-business-intelligence-groovy.html"&gt;a recent article on Forbes.com&lt;/a&gt;, Dan Woods makes the case for Groovy in companies that already use Java.  The whole article is good, but this line pretty much sums it up: &lt;b&gt;“For a company with a heavy investment in Java, Groovy should be a no-brainer.”&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I'm not saying that every Java developer should start using Grails, though that might not be a bad idea. :-)  There are some that prefer a component-based framework such as JSF or Wicket to a page based framework like Grails.  That's fine: with JSF 2.0 and its Groovy support, JSF is showing some promise.&lt;/p&gt;&lt;p&gt;The bottom line is to use the framework that will help your team be the most productive and do the best job. But we need to get beyond the “we can't use Grails because we are a Java shop” stuff.  It just doesn't make sense.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/3Dt2KE2gAAs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/5291480775664856929/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=5291480775664856929" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/5291480775664856929?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/5291480775664856929?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/3Dt2KE2gAAs/grails-makes-sense.html" title="Grails: It Just Makes Sense" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>8</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/02/grails-makes-sense.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUMQnkzfSp7ImA9WxBWE0Q.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-6638097175931386891</id><published>2010-02-05T09:00:00.000-08:00</published><updated>2010-02-05T10:08:03.785-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-05T10:08:03.785-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>My Favorite Tool</title><content type="html">Years ago, I worked in construction, building houses. My favorite tool was my Estwing 28oz. waffle-headed framing hammer.  I could drive a 16d nail in one hit with that hammer.  (I also got carpal tunnel syndrome from using that hammer. But that's a different story.)&lt;br /&gt;&lt;br /&gt;That hammer, because of its characteristics (its weight, its size, the pattern on its face, its textured grip, etc.), allowed me to do what I needed to do.  Beyond that, it made it &lt;span style="font-style: italic;"&gt;easier&lt;/span&gt; for me to do what I needed to do.  No actually, that's not quite accurate.&lt;br /&gt;&lt;br /&gt;The hammer didn't help me do what I &lt;span style="font-weight: bold;"&gt;needed&lt;/span&gt; to do.  &lt;span style="font-style: italic;"&gt;It helped me to do what I &lt;/span&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;chose&lt;/span&gt;&lt;span style="font-style: italic;"&gt; to do&lt;/span&gt;.  In general, I chose to do what I needed to do, but the hammer played no part in that.  I had a good boss on that job, and he helped me to determine what I needed to do.  I also worked with some very experienced carpenters on that job, and they helped me to learn the right way to do what I needed to do.  All the while, my trusty hammer was there just making things easier.&lt;br /&gt;&lt;br /&gt;Not all of the tools I used were that way.  My circular saw had a safety guard on it that made it difficult to see where I was cutting, and it got in the way when first starting a cut.  It would then slide away as I went, but I would often hold it back out of the way when I was starting.  The more experienced carpenters just &lt;span style="font-weight: bold;"&gt;removed their safety guards&lt;/span&gt; altogether.  I'm sure there were accidents that the safety guards would have prevented, but I guess &lt;span style="font-weight: bold;"&gt;they were rare enough that most folks decided that the productivity gains were worth the risk&lt;/span&gt;.  I was always amazed at how fast those guys could frame a house!&lt;br /&gt;&lt;br /&gt;I used my saw because I needed to use it, and it was much faster than using a hand saw, but I don't look back at my saw with the same fondness as that hammer.  In fact, I can't even remember what brand or model it was.  There's just something about a tool that feels good to use: a tool that helps you do what you want to do, and then just stays out of your way.&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/5oPC_nX2gks" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/6638097175931386891/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=6638097175931386891" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6638097175931386891?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6638097175931386891?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/5oPC_nX2gks/my-favorite-tool.html" title="My Favorite Tool" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/02/my-favorite-tool.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IGRXc_cSp7ImA9WxBXFUQ.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-6671994731128367984</id><published>2010-01-27T05:17:00.000-08:00</published><updated>2010-01-27T05:38:44.949-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-27T05:38:44.949-08:00</app:edited><title>Groovy and Grails in The Gateway City</title><content type="html">On January 5th, the &lt;a href="http://gatewaygroovy.org"&gt;Gateway Groovy Users&lt;/a&gt; had their 2010 kick-off meeting.  The turn-out was amazing.  When we were discussing the plans to get the group going again (after a 6 month hiatus), we thought we might be able to get our attendance numbers up to 10 or 12 (from the previous record of 7).  We ended up with over 50 people!  We even had such St. Louis Groovy icons as &lt;a href="http://javajeff.blogspot.com/"&gt;Jeff Brown&lt;/a&gt; and &lt;a href="http://kensipe.blogspot.com/"&gt;Ken Sipe&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We're hoping to keep that momentum going with our next meeting, on February 2nd.  Seth Havermann will be giving a presentation on and demonstration of &lt;a href="http://groovy.codehaus.org/Swing+Builder"&gt;Groovy's SwingBuilder&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Then we'll turn it up a notch in March, with &lt;a href="http://tech.puredanger.com"&gt;Alex Miller&lt;/a&gt; presenting on &lt;a href="http://gpars.codehaus.org/"&gt;GPars&lt;/a&gt; (officially pronounced like “Jeepers”), the Groovy concurrency library.  Perhaps we can get our sponsor to bring nachos.&lt;br /&gt;&lt;br /&gt;As excited as I am about the response to the &lt;a href="http://gatewaygroovy.org"&gt;Gateway Groovy Users&lt;/a&gt; meetings, I am even more thrilled to see that this is not an isolated phenomenon.  Groovy and Grails groups continue to pop up around the globe, and those that have been going for a while are reporting continued success.&lt;br /&gt;&lt;br /&gt;One of the first Groovy user groups in the US, the &lt;a href="http://groovy.mn"&gt;Groovy Users of Minnesota&lt;/a&gt; (GUM – you gotta love that name!), provided the inspiration for the first US-based, community-driven Groovy conference: &lt;a href="http://gr8conf.org/blog/2009/12/02/47"&gt;GR8 in the US&lt;/a&gt;, to be held April 16th, 2010 in Bloomington, Minnesota.&lt;br /&gt;&lt;br /&gt;To find out about other &lt;a href="http://groovy.codehaus.org"&gt;Groovy&lt;/a&gt;, &lt;a href="http://grails.org"&gt;Grails&lt;/a&gt;, and &lt;a href="http://griffon.codehaus.org"&gt;Griffon&lt;/a&gt; user groups, or to help get one started, check out &lt;a href="http://g2groups.net/"&gt;http://g2groups.net&lt;/a&gt;.  The Groovy community continues to grow, to thrive, to amaze, and to inspire.&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/U8ChjBlR6mo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/6671994731128367984/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=6671994731128367984" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6671994731128367984?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/6671994731128367984?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/U8ChjBlR6mo/groovy-and-grails-in-gateway-city.html" title="Groovy and Grails in The Gateway City" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2010/01/groovy-and-grails-in-gateway-city.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0EBQH89eSp7ImA9WxBSGEo.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-1507215525683981084</id><published>2009-12-26T15:14:00.000-08:00</published><updated>2009-12-26T15:54:11.161-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-26T15:54:11.161-08:00</app:edited><title>GroovyMag Plugin Corner: Feeds Plugin</title><content type="html">&lt;span style="font-style:italic;"&gt;The following post is a reprint of the Plugin Corner article for the January 2009 issue of GroovyMag.  You can find this and other past issues at &lt;a href="http://groovymag.com"&gt;http://groovymag.com&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;RSS and Atom feeds are becoming more popular and consequently more important to include in our applications. The battle for mindshare among our users or potential users is constant, and having a feed available is one of our more effective weapons.&lt;br /&gt;&lt;br /&gt;But feeds are complicated, right? There are so many different formats and versions and then there's all that XML- don't get me started on XML! Not to worry; some of the smart people at Sun came up with the ROME API that encapsulates and simplifies much of what goes into an RSS/Atom feed. So, all we have to do is learn a new Java API. NOT! This is Grails we're talking about. In steps Groovy Award winner Marc Palmer with the Feeds Plugin.&lt;br /&gt;&lt;br /&gt;This plugin wraps the ROME API and gives us the very groovy &lt;code&gt;FeedBuilder&lt;/code&gt; with its powerful yet simple DSL. Once installed, the Feeds Plugin gives us a new version of the familiar &lt;code&gt;render()&lt;/code&gt; method. Now we can just “render" a feed instead of a view. Let's get started.&lt;br /&gt;&lt;br /&gt;For our example, we are going to build a book of the month feed. We already have a &lt;code&gt;Book&lt;/code&gt; domain class with corresponding controller and views.&lt;br /&gt;&lt;br /&gt;First install the plugin:&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;grails install-plugin feeds&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That was pretty painless. Now we will add a new action to our controller:&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;def monthly = {&lt;br /&gt; render(feedType:"atom"){&lt;br /&gt;   title="Book of the Month"&lt;br /&gt;   link="http://localhost:8080/bom/book/monthly/feed"&lt;br /&gt;   description="A monthly book recommendation"&lt;br /&gt;     def book = bookOfTheMonth() //complex algorithm here :)&lt;br /&gt;     if(book){&lt;br /&gt;       entry{&lt;br /&gt;         title = book.title&lt;br /&gt;         link="${g.createLink(action:''show'', id:book.id)}"&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;code&gt;render()&lt;/code&gt; method now takes a &lt;code&gt;feedType&lt;/code&gt; parameter. It is this parameter that tells the plugin that this is indeed a feed. If that parameter is there, we can also include a &lt;code&gt;version&lt;/code&gt; parameter to specify the version of the feed format we are using. The defaults are &lt;code&gt;2.0&lt;/code&gt; for RSS and &lt;code&gt;1.0&lt;/code&gt; for Atom. Next the &lt;code&gt;render()&lt;/code&gt; method takes a closure where we can set the various properties of our feed and entries. In our example we are setting the &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;link&lt;/code&gt;, and &lt;code&gt;description&lt;/code&gt; properties on our feed and then including one entry for the book of the month. Since the &lt;code&gt;FeedBuilder&lt;/code&gt; DSL is still Groovy code, we can handle any logic that is needed. Here, for example, we are only creating an entry if our &lt;code&gt;book&lt;/code&gt; is not null.&lt;br /&gt;&lt;br /&gt;Next we create our &lt;code&gt;entry&lt;/code&gt;. The &lt;code&gt;entry&lt;/code&gt; node also takes a closure where we will set the various properties of the entry. All we are doing with our entry is giving it a &lt;code&gt;title&lt;/code&gt; (the book's title) and a link to the show page for that book. Now if we run our application and subscribe to the feed at http://localhost:8080/bom/book/monthly we will get&lt;br /&gt;something like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Mt9WQBouLcM/SzadS1gz9OI/AAAAAAAAAMU/v8SshOPTE8U/s1600-h/feeds1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px; height: 113px;" src="http://3.bp.blogspot.com/_Mt9WQBouLcM/SzadS1gz9OI/AAAAAAAAAMU/v8SshOPTE8U/s200/feeds1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5419692148514878690" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I know- kind of boring. Let's add another feed to our application that will give us a bit more to look at. Some of us are more voracious readers than others so we might want to have a list of books all at once rather than one each month. Here's a new controller action that will give us just that:&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;def booklist={&lt;br /&gt;  render(feedType:"atom"){&lt;br /&gt;    title="Groovy Books"&lt;br /&gt;    link="http://localhost:8080/bom/book/booklist/feed"&lt;br /&gt;    description="A listing of Groovy and Grails books"&lt;br /&gt;      def books = Book.list()&lt;br /&gt;      books.each{book -&gt;&lt;br /&gt;        entry(book.title){&lt;br /&gt;          link="${g.createLink(action:''show'', id:book.id)}"&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now if we subscribe to http://localhost:8080/bom/book/monthly we will get a bit more content from our feed:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Mt9WQBouLcM/SzafQ4rxQMI/AAAAAAAAAMc/L2ln0DzhCSQ/s1600-h/feeds2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 199px; height: 200px;" src="http://1.bp.blogspot.com/_Mt9WQBouLcM/SzafQ4rxQMI/AAAAAAAAAMc/L2ln0DzhCSQ/s200/feeds2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5419694314029662402" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There is a great deal more that can be done with the Feeds Plugin than what we demonstrated here, so when you're ready to dig deeper, the official documentation is at &lt;a href="http://grails.org/plugin/feeds"&gt;http://grails.org/plugin/feeds&lt;/a&gt;. You can also find lots of information on the ROME API at the java.net site: &lt;a href="http://rome.dev.java.net"&gt;http://rome.dev.java.net&lt;/a&gt;. As always, another excellent source of information is the plugin source itself. The Feeds Plugin source can be found in plugins/feedsx.x/ Much of the meat of the plugin is in src/groovy/feedplugin/FeedBuilder.groovy.&lt;br /&gt;&lt;br /&gt;Even without digging in to the docs or source, you can see how easy it is to add basic RSS/Atom feeds to your application with the Feeds plugin. Now you can set your mind to work on finding new and innovative ways to use them. Once again Grails and Grails plugins take away the drudgery and leave us with the fun!&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/iP3KAvLx9m0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/1507215525683981084/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=1507215525683981084" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/1507215525683981084?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/1507215525683981084?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/iP3KAvLx9m0/feeds-plugin.html" title="GroovyMag Plugin Corner: Feeds Plugin" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_Mt9WQBouLcM/SzadS1gz9OI/AAAAAAAAAMU/v8SshOPTE8U/s72-c/feeds1.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2009/12/feeds-plugin.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0ANR3c-fip7ImA9WxBTEkQ.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-8661983053852072885</id><published>2009-12-08T07:33:00.001-08:00</published><updated>2009-12-08T10:09:56.956-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-08T10:09:56.956-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Pragmatic Programmers" /><category scheme="http://www.blogger.com/atom/ns#" term="Pomodoro" /><category scheme="http://www.blogger.com/atom/ns#" term="Book Review" /><title>Pomodoro Technique Illustrated - A Brief Review</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Mt9WQBouLcM/Sx0Mh6ui-2I/AAAAAAAAALY/6KuywvUSyGA/s1600-h/snfocus.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 166px; height: 200px;" src="http://1.bp.blogspot.com/_Mt9WQBouLcM/Sx0Mh6ui-2I/AAAAAAAAALY/6KuywvUSyGA/s200/snfocus.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5412496104008907618" /&gt;&lt;/a&gt;&lt;br /&gt;If you would like to be more productive and you haven't looked into the Pomodoro technique, you need to get a hold of the new Pragmatic Bookshelf book, &lt;a href="http://bit.ly/6NfDHF"&gt;&lt;em&gt;Pomodoro Technique Illustrated&lt;/em&gt;&lt;/a&gt;, by Staffan Nöteberg.&lt;br /&gt;&lt;br /&gt;I had heard about the Pomodoro technique, and knew it had something to do with a kitchen timer, but that was about the extent of my understanding of this powerful technique. Staffan Nöteberg not only shows us how we can become much more productive with the Pomodoro technique, but he also shows us just how much we can learn from a cucumber and an artichoke.  (You'll just have to read the book to understand that one.)  Staffan's writing style and illustrations make this book easy and fun to read, but it's the simplicity and the "why didn't I think of that" nature of the technique that really pulls you in.  &lt;br /&gt;&lt;br /&gt;We may have hours in a day to spend to accomplish a task, but it's nearly impossible (for some of us, entirely impossible) to spend that time focused on that task without distractions and interruptions.  The Pomodoro technique takes that into account with the obvious (in hindsight) observation that though we may not be able to focus on one thing for a lengthy period, we probably can for a short one.&lt;br /&gt;&lt;br /&gt;Using a timer to discipline ourselves to focus on one thing for a short time (typically 25 minutes, but you can start smaller) is a key component of the technique, but there's more to it than that.  It is a whole system of capturing, prioritizing, tracking and accomplishing what we want to get done.  All of this is done with the simplest of tools: a timer, a piece of paper, and a pencil.  &lt;br /&gt;&lt;br /&gt;It's kind of like breaking your work day into a series of 25 minute iterations, complete with a micro-retrospective after each one.  Then a break - to clear your mind, check email, Twitter, &lt;a href="http://www.groovyblogs.org/"&gt;Groovyblogs&lt;/a&gt;, etc. Then back to it again for another iteration.  &lt;br /&gt;&lt;br /&gt;Just like with a development process, you may get some benefit from using pieces of the technique, like the timer, but you'll get much more if you use the whole thing.  This book is a great way to get started.  Once you do, you'll want to give it some time to get into the habit.  I'm still working on it myself, and I have already seen an improvement.  &lt;br /&gt;&lt;br /&gt;&lt;em&gt;Pomodoro Technique Illustrated&lt;/em&gt; is now shipping. You can get your copy and get started at &lt;a href="http://pragprog.com"&gt;http://pragprog.com&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;There goes the timer.  Finished just in time!&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/DZyD9RVpKP4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/8661983053852072885/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=8661983053852072885" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/8661983053852072885?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/8661983053852072885?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/DZyD9RVpKP4/pomodoro-technique-illustrated-brief_08.html" title="Pomodoro Technique Illustrated - A Brief Review" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_Mt9WQBouLcM/Sx0Mh6ui-2I/AAAAAAAAALY/6KuywvUSyGA/s72-c/snfocus.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2009/12/pomodoro-technique-illustrated-brief_08.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUASHkyfyp7ImA9WxNaFkQ.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-1653915012363483697</id><published>2009-12-01T08:42:00.001-08:00</published><updated>2009-12-01T10:30:49.797-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-01T10:30:49.797-08:00</app:edited><title>GroovyMag Plugin Corner: Testing</title><content type="html">&lt;em&gt;In the December 2008 issue of &lt;a href="http://groovymag.com"&gt;GroovyMag&lt;/a&gt;, I covered the Grails Testing plugin.  This plugin provided the new Grails 1.1 testing features to 1.0.x applications.  With that in mind, this may seem a bit out of date. But I happen to know that there are still some applications being developed in Grails 1.0.4, and the classes and methods described here, though built-into Grails 1.1 and above, are still applicable.  So, just to be clear: If you are using Grails 1.1 or above, you can still use these classes / methods, but you don't have to install the plugin.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;When writing unit tests, the goal is to test a single class in isolation, with any collaborating objects being replaced by mocks or stubs. This will lead to less fragile code that can work with different implementations of collaborating objects, and it will help to isolate bugs when they appear. Unit tests are also much faster to run, since they don’t require resource-intensive services and containers to be loaded. However, with all of the functionality that Grails magically adds to your domain classes, controllers, services, and taglibs, it can be quite difficult to write unit tests for these artifacts. It can be done, and I know several determined developers who have, but many others just take the easy (and slow) road and write only integration tests. Some take the dead-end road and write no tests at all. Integration tests test a class with its collaborators, which means that the Grails goodness is all there for you. These tests are important to have, but they should not take the place of unit tests. Another concern with integration tests as your only automated tests is that they take much longer to run, which means that they will likely be run less often.&lt;br /&gt;&lt;br /&gt;Well, now there is no excuse not to write unit tests for your Grails applications. In this Plugin Corner we will see how the Testing plugin, by Peter Ledbrook, makes it plain easy to write unit tests for Grails artifacts (domain classes, controllers, services and taglibs). This plugin does for unit testing what GORM does for persistence. It provides mock implementations of almost all of the dynamic methods added to your artifacts by Grails. The plugin includes four new &lt;code&gt;TestCase&lt;/code&gt; classes that all descend from &lt;code&gt;GroovyTestCase&lt;/code&gt;, which itself extends from JUnit’s &lt;code&gt;TestCase&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Mt9WQBouLcM/SxH91F0TanI/AAAAAAAAALI/fq4nnng4Njw/s1600/testclasses.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 247px;" src="http://3.bp.blogspot.com/_Mt9WQBouLcM/SxH91F0TanI/AAAAAAAAALI/fq4nnng4Njw/s320/testclasses.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5409383715985123954" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;GrailsUnitTestCase&lt;/code&gt; introduces most of the powerful meta-programming magic in this plugin, and it will be sufficient for testing domain classes and services that use domain classes. For testing controllers and TagLibs you can probably guess which classes to use.&lt;br /&gt;&lt;br /&gt;Let’s take a look at just how easy-to-use and powerful this plugin is. First we’ll install it:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;grails install-plugin testing&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now to take advantage of the goodness this plugin gives us, we just need to have our unit tests extend one of the new &lt;code&gt;TestCase&lt;/code&gt; classes. In the following example we’ll extend the &lt;code&gt;ControllerUnitTestCase&lt;/code&gt; class.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;class BookControllerTests extends grails.test.ControllerUnitTestCase{&lt;br /&gt;  def b1, b2&lt;br /&gt;&lt;br /&gt;  void setUp(){&lt;br /&gt;    super.setUp()&lt;br /&gt;    controller = new BookController()&lt;br /&gt;    b1 = new Book(title:’Programming Groovy’, author:’Venkat Subramaniam’)&lt;br /&gt;    b2 = new Book(title:’Grails in Action’, author:’Glen Smith’)&lt;br /&gt;    mockDomain(Book, [b1, b2])&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;ControllerUnitTestCase&lt;/code&gt; has a protected &lt;code&gt;controller&lt;/code&gt; property. In our &lt;code&gt;setup()&lt;/code&gt; method we set this property to a new instance of our &lt;code&gt;BookController&lt;/code&gt;. Then we create a couple &lt;code&gt;Book&lt;/code&gt; instances and call the uber cool &lt;code&gt;mockDomain()&lt;/code&gt; method. This method takes a class (&lt;code&gt;Book&lt;/code&gt;) and a list (&lt;code&gt;[b1, b2]&lt;/code&gt;). Once this method has been called, we can call methods like &lt;code&gt;list()&lt;/code&gt;, &lt;code&gt;get()&lt;/code&gt;, &lt;code&gt;save()&lt;/code&gt;, &lt;code&gt;delete()&lt;/code&gt;, and even &lt;code&gt;findAllByXXX()&lt;/code&gt;. The list becomes an in-memory database. In our example we passed two existing instances in the list. When we called &lt;code&gt;mockDomain()&lt;/code&gt;, the object instances in the list were “saved” to the list. Alternatively, we could have passed in an empty list and added the instances by calling &lt;code&gt;save()&lt;/code&gt;. In either case, the objects are assigned &lt;code&gt;id&lt;/code&gt; values based on the order they are added. This is important, because most of the actions in a standard Grails controller use the &lt;code&gt;id&lt;/code&gt; property to find objects.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;  void testShow(){&lt;br /&gt;    controller.params.id = 1&lt;br /&gt;    def model = controller.show()&lt;br /&gt;    assertEquals(b1, model.bookInstance)&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When we call our controller’s &lt;code&gt;show&lt;/code&gt; action it will call &lt;code&gt;Book.get()&lt;/code&gt;. This will be performed by the mock implementation of &lt;code&gt;get()&lt;/code&gt; that was added to &lt;code&gt;Book&lt;/code&gt; when we called &lt;code&gt;mockDomain()&lt;/code&gt;, which will retrieve the instance from the list. I point this out because the Testing plugin makes working with domain classes so seamless that it sometimes feels like we’re still writing integration tests.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;  void testBookNotFound(){&lt;br /&gt;    controller.params.id = 3&lt;br /&gt;    controller.show()&lt;br /&gt;    assertEquals(“Book not found with id 3”, mockFlash.message)&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In our second test we set &lt;code&gt;params.id&lt;/code&gt; to a number we know does not exist, to ensure that the proper error message is stored in the flash scope. Notice that what we check is not &lt;code&gt;flash&lt;/code&gt; but &lt;code&gt;mockFlash&lt;/code&gt;. &lt;code&gt;mockFlash&lt;/code&gt; is a &lt;code&gt;Map&lt;/code&gt; that is declared in the &lt;code&gt;MVCUnitTestCase&lt;/code&gt;, the super class of the &lt;code&gt;ControllerUnitTestCase&lt;/code&gt;. &lt;code&gt;MVCUnitTestCase&lt;/code&gt; also introduces &lt;code&gt;mockRequest&lt;/code&gt;, &lt;code&gt;mockResponse&lt;/code&gt;, &lt;code&gt;mockSession&lt;/code&gt;, and more.&lt;br /&gt;&lt;br /&gt;A unit test for the scaffolded actions is of questionable value, so let’s try a unit test for a custom service. Our service method creates a batch of &lt;code&gt;Publisher&lt;/code&gt;s and &lt;code&gt;Book&lt;/code&gt;s from XML data. Here’s the test:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;class BatchServiceTests extends GrailsUnitTestCase {&lt;br /&gt;  def batchService&lt;br /&gt;  def bookInstances = []&lt;br /&gt;  def publisherInstances = []&lt;br /&gt;&lt;br /&gt;  void setUp(){&lt;br /&gt;    super.setUp()&lt;br /&gt;    mockDomain(Book, bookInstances)&lt;br /&gt;    mockDomain(Publisher, publisherInstances)&lt;br /&gt;    batchService = new BatchService()&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This test class extends &lt;code&gt;GrailsUnitTestCase&lt;/code&gt; because we need the domain class mocking, but we do not need the features introduced in &lt;code&gt;MVCUnitTestCase&lt;/code&gt; or later. We are defining the lists that will be passed to &lt;code&gt;mockDomain()&lt;/code&gt; ahead of time, since we are not creating any domain instances in our test. Notice also that we are mocking both the &lt;code&gt;Publisher&lt;/code&gt; and the &lt;code&gt;Book&lt;/code&gt; domains. This will enable us to mock the relationship logic as well. Finally we create an instance of the service that we are going to test.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;  void testLoadBooks() {&lt;br /&gt;    def data = “””&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;publishers&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;publisher name=”Apress”&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;book title=”Definitive Guide to Grails” author=”Graeme Rocher”/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;book title=”Beginning Groovy and Grails” author=”Christopher Judd”/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/publisher&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;publisher name=”Manning”&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;book title=”Groovy in Action” author=”Dierk Koenig”/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/publisher&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;/publishers&amp;gt;&lt;br /&gt;    “””&lt;br /&gt;&lt;br /&gt;    batchService.loadBooks(data)&lt;br /&gt;    def p = Publisher.findByName(‘Apress’)&lt;br /&gt;    assertEquals(2, p.books.size())&lt;br /&gt;    assertEquals(“Groovy in Action”, Book.findByAuthor(“Dierk Koenig”).title)&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;After calling our service’s &lt;code&gt;loadBooks()&lt;/code&gt; we are able to call &lt;code&gt;Publisher.findByName()&lt;/code&gt; to verify that the two books by Apress are there. We also verify that Dierk’s classic work is there by calling &lt;code&gt;Book.findByAuthor()&lt;/code&gt;. These finder methods are not available in unit tests, but the Testing plugin is providing mock implementations of them using object instances held in lists.&lt;br /&gt;&lt;br /&gt;Here’s a snippet of our &lt;code&gt;BatchService.loadBooks()&lt;/code&gt; method:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;  def loadBooks(String data) {&lt;br /&gt;    def publishers = new XmlSlurper().parseText(data)&lt;br /&gt;    publishers.publisher.each {pub -&gt;&lt;br /&gt;      def p = new Publisher(name:pub.@name.text())&lt;br /&gt;      pub.book.each{book -&gt;&lt;br /&gt;        def b = new Book(title:book.@title.text(), author:book.@author.text())&lt;br /&gt;        p.addToBooks(b)&lt;br /&gt;      }&lt;br /&gt;      p.save()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice how we are calling &lt;code&gt;Publisher.addToBooks()&lt;/code&gt; to place the &lt;code&gt;Book&lt;/code&gt; instances in the &lt;code&gt;Publisher&lt;/code&gt;’s &lt;code&gt;books&lt;/code&gt; collection and finally calling &lt;code&gt;p.save()&lt;/code&gt;. These methods are also being mocked by the Testing plugin. Again it’s easy to forget that we’re writing unit tests and not integration tests, that is until we see how fast they run!&lt;br /&gt;&lt;br /&gt;The documentation on the Testing plugin is pretty good, but still leaves some holes. If you want to take full advantage of the plugin I recommend reading through the source code that is included in your project once you install the plugin. It’s mostly Groovy code so, of course, it reads like a good novel. There are also some other resources on the web to help you get going.&lt;br /&gt;&lt;br /&gt;With this plugin there is really no need to fear unit testing your Grails artifacts. So, if you’ve been writing integration tests instead of unit tests or if you are not writing any tests&lt;br /&gt;at all, then run (don’t walk) to your nearest Grails project and install this plugin. You’ll be glad you did and so will your team mates, your manager, your customers, your spouse, your neighbors...&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;br /&gt;Official Plugin Documentation: &lt;a href="http://grails.org/Testing+Plugin"&gt;http://grails.org/Testing+Plugin&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Mike Hugo’s presentation to the Groovy Users of Minnesota: &lt;a href="http://www.piragua.com/2008/11/12/testing-plugin-presentation"&gt;http://www.piragua.com/2008/11/12/testing-plugin-presentation&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Robert Fletcher’s very helpful blog post:&lt;br /&gt;&lt;a href="http://stateyourbizness.blogspot.com/2008/08/unit-testing-controllers-with-testing.html"&gt;http://stateyourbizness.blogspot.com/2008/08/unit-testing-controllers-with-testing.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/fWiKoobumI0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/1653915012363483697/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=1653915012363483697" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/1653915012363483697?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/1653915012363483697?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/fWiKoobumI0/testing-plugin.html" title="GroovyMag Plugin Corner: Testing" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_Mt9WQBouLcM/SxH91F0TanI/AAAAAAAAALI/fq4nnng4Njw/s72-c/testclasses.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2009/12/testing-plugin.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8AQn05eip7ImA9WxNaEUU.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-8082862524036252836</id><published>2009-11-25T13:51:00.000-08:00</published><updated>2009-11-25T14:24:03.322-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-25T14:24:03.322-08:00</app:edited><title>GroovyMag Plugin Corner: Searchable</title><content type="html">&lt;em&gt;Over the next few months, I will be reprinting some of the Plugin Corners that I've written for &lt;a href="http://groovymag.com"&gt;GroovyMag&lt;/a&gt;. Hopefully this will give you a taste of what you can find in GroovyMag each month (and keep my blog from being so dead). Enjoy!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;From November 2008 issue&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;One of the most powerful Grails plugins is also one of the easiest to use. The Searchable plugin brings the power of the Compass search engine into Grails in a very Groovy way. If you haven’t tried the Searchable plugin yet, it’s time to stop making excuses and stop wasting time building complex search forms for your projects. Let’s get started.&lt;br /&gt;&lt;br /&gt;The first step to using any plugin is to install it. From the root of your Grails project execute the following command:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;grails install-plugin searchable&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now the fun begins. To make a domain class searchable, just add the &lt;code&gt;static searchable&lt;/code&gt; flag to the class. Here’s our &lt;code&gt;Book&lt;/code&gt; class, for example:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;class Book {&lt;br /&gt; static Searchable = true&lt;br /&gt; String title&lt;br /&gt; Integer pages&lt;br /&gt; Author author&lt;br /&gt;&lt;br /&gt; String toString(){title}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We’ve already generated the scaffolding for this class, so now let’s add a &lt;code&gt;search&lt;/code&gt; action to our &lt;code&gt;BookController&lt;/code&gt; like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;def search = {&lt;br /&gt; def bookList = Book.search(params.&lt;br /&gt;query).results&lt;br /&gt; render(view:’list’, model:[bookList:&lt;br /&gt;bookList])&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In order to call our new &lt;code&gt;search&lt;/code&gt; action we will need a form, so we’ll add one to the generated list view. Put the following block of code right before the opening &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; tag in list.gsp:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:html"&gt;&lt;br /&gt;&amp;lt;div class=”nav”&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;g:form name=”search” action=’search’&amp;gt;&lt;br /&gt;&lt;br /&gt;  Search:&lt;br /&gt;&lt;br /&gt;  &amp;lt;input type=”text” name=”query” value=”${query}”/&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;input type=”submit” value=”Search”/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/g:form&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now if we run our application - with a little data thrown in via the bootstrap - we’ll get something like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Mt9WQBouLcM/Sw2qJZvyH5I/AAAAAAAAALA/Zv06OuUnEto/s1600/screen.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 310px; height: 320px;" src="http://3.bp.blogspot.com/_Mt9WQBouLcM/Sw2qJZvyH5I/AAAAAAAAALA/Zv06OuUnEto/s320/screen.png" alt="" id="BLOGGER_PHOTO_ID_5408165806048681874" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We can now search for any string value across any of the properties of our Book instances from a single input field. We can search the String properties as well as the Integers. For example, if we had a book called “200 Reasons to Use Grails,” and we searched for the value 200, we would find&lt;br /&gt;that book along with any books that had exactly 200 pages.&lt;br /&gt;&lt;br /&gt;Although the default behavior is to search across all the properties, we can search a specific property by prefacing the search value with propertyName: (eg: author:Rocher).&lt;br /&gt;&lt;br /&gt;I should point out that the code we have right now will blow up if the user doesn’t enter any search value before submitting the form. Don’t worry - this is easy to fix. The dynamic &lt;code&gt;search&lt;/code&gt; method that is added to our &lt;code&gt;Book&lt;/code&gt; class by the Searchable plugin returns an instance of the &lt;code&gt;SearchResult&lt;/code&gt; class. This class contains a property called ‘&lt;code&gt;results&lt;/code&gt;’, which is an &lt;code&gt;ArrayList&lt;/code&gt;. This is why we can so easily return it in the model to our list view. So if there is no search value we can just call &lt;code&gt;Book.list()&lt;/code&gt; and return that instead. Let’s modify our &lt;code&gt;search&lt;/code&gt; action to look more like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;def search = {&lt;br /&gt; def bookList&lt;br /&gt; if (params.query)&lt;br /&gt;   bookList = Book.search(params.query).results&lt;br /&gt; else&lt;br /&gt;   bookList = Book.list()&lt;br /&gt; render(view:’list’, model:[bookList:bookList])&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We’re not using any additional parameters here, but the &lt;code&gt;search()&lt;/code&gt; method takes all the same parameters that the &lt;code&gt;list()&lt;/code&gt; method takes - which is important when it comes to sorting and pagination. In order to make pagination work with the Searchable plugin, we need to make a few simple changes. First we’ll need to pass a couple extra pieces of information to the view. The &lt;code&gt;SearchResult&lt;/code&gt; returned by the &lt;code&gt;search()&lt;/code&gt; method will be used to determine the total number of objects found, and the &lt;code&gt;query&lt;/code&gt; parameter will be passed back to the view so that it can be reused when loading subsequent pages. So now our &lt;code&gt;search&lt;/code&gt; action will look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;def search = {&lt;br /&gt; def bookList&lt;br /&gt; if (params.query){&lt;br /&gt;   def searchResult = Book.search(params.query)&lt;br /&gt;   bookList = searchResult.results&lt;br /&gt; }&lt;br /&gt; else&lt;br /&gt;   bookList = Book.list()&lt;br /&gt; render(view:’list’, model:[bookList:bookList, searchResult:searchResult, query:params.query])&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we will modify list.gsp, but since we are using the same view for both the list and search actions, we will put our changes within a g:if tag. If we are viewing search results we will modify the g:paginate tag to make use of the new values we passed in on the model. Otherwise, we will use the original g:paginate tag.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:html"&gt;&lt;br /&gt;&amp;lt;g:if test=”${searchResult}”&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;lt;g:paginate total=”${searchResult.total}” params=”[query:query]” /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/g:if&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;g:else&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;lt;g:paginate total=”${Book.count()}”/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/g:else&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In keeping with the Grails way, the Searchable plugin gives you sensible defaults for most settings but allows for much more customization if needed. To add this, just install the SearchableConfiguration.groovy file by executing the following command:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:bash"&gt;&lt;br /&gt;grails install-searchable-config&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can get more details about what you can do with this file as well as excellent documentation on the Searchable plugin page at grails.org (see references). Hopefully this tutorial will give you enough to get you going. Once you get started, more questions will undoubtedly arise, so I’ve included a list of references below.&lt;br /&gt;&lt;br /&gt;The Searchable plugin makes including powerful full text searching so easy to do that there’s really no reason to not take advantage of it. So dig in and have fun!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;br /&gt;&lt;a href="http://grails.org/Searchable+Plugin"&gt;http://grails.org/Searchable+Plugin&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.grails.org/Searchable+Plugin+-+Configuration"&gt;http://www.grails.org/Searchable+Plugin+-+Configuration&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.grails.org/Searchable+Plugin+-+Searching"&gt;http://www.grails.org/Searchable+Plugin+-+Searching&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.compass-project.org/"&gt;http://www.compass-project.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://lucene.apache.org/"&gt;http://lucene.apache.org/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/fxNLglXGEy8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/8082862524036252836/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=8082862524036252836" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/8082862524036252836?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/8082862524036252836?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/fxNLglXGEy8/searchable-plugin.html" title="GroovyMag Plugin Corner: Searchable" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_Mt9WQBouLcM/Sw2qJZvyH5I/AAAAAAAAALA/Zv06OuUnEto/s72-c/screen.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2009/11/searchable-plugin.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMFQno5eip7ImA9WhRQE0s.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-5303801655070281284</id><published>2009-11-18T05:55:00.000-08:00</published><updated>2011-12-08T10:03:33.422-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-08T10:03:33.422-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Boeing" /><category scheme="http://www.blogger.com/atom/ns#" term="Contegix" /><category scheme="http://www.blogger.com/atom/ns#" term="zombies" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Slaying Hallway Zombies</title><content type="html">For the past few months, I have been working on a project for a &lt;a href="http://www.cdgnow.com/"&gt;division of Boeing&lt;/a&gt;.  It was a bit of a culture shock, going from a small, dynamic, family feeling company like &lt;a href="http://contegix.com/"&gt;Contegix&lt;/a&gt; to one of the largest companies in the world.  But it's a Grails project, and the prospect of helping all of those oppressed Boeing Java devs get into Grails is well worth the cross-cultural experience.  :-)&lt;br /&gt;&lt;br /&gt;So, what does that have to do with zombies?  Well, when working for a huge company, one often ends up in a huge building.  And in huge buildings, we often find very long hallways.  The building I work in has hallways that are several hundred feet long (almost 150 meters).  Something strange happens to (otherwise friendly) people when they walk down long hallways.  They become &lt;span style="font-weight: bold;"&gt;hallway zombies&lt;/span&gt;.  Hallway zombies aren't like other zombies &amp;#8212; they aren't decaying (usually), and they don't try eat your brains.  But if you&amp;#8217;re not careful, they will rob your joy.  There&amp;#8217;s something unnatural about walking directly past another person and not even acknowledging that they exist.  But if you don&amp;#8217;t fight it, it will start to become natural to you.  And then you will have become a hallway zombie yourself!&lt;br /&gt;&lt;br /&gt;Hallway zombies can be defeated, though, and fortunately you don't even have to decapitate them. (How would that look on a reference letter?)  Some hallway zombies can be defeated with a simple smile.  Some may take repeated smiles.  The first smiles may seem to bounce right off of them, but if you keep it up, you will start to break through.  Others are tougher and may require more drastic action, such as a full round-house &amp;#8220;Good morning!&amp;#8221;&lt;br /&gt;&lt;br /&gt;Those are the basic weapons for fighting hallway zombies &amp;#8212; and fight you must, or your fate is sealed.  But these weapons are much more effective with a good technique.  If you spot a hallway zombie coming towards you a couple hundred feet away and you start smiling at them right away, they will be able to defend against it.  It's best to catch them by surprise.  Let them think you&amp;#8217;re one of them.  Look straight ahead, or down at the floor.  (Don't be tempted to take furtive glances into open office doors or down a row of cubicles.  That's a dead give-away.)  Then, when you are within 15 to 20 feet of passing, strike quickly with your best smile and even a nod of the head.  If you're pulling out the big guns, you can start a bit sooner, just in case you see an opening for a &amp;#8220;How&amp;#8217;s it going?&amp;#8221; to follow up on your &amp;#8220;Good morning!&amp;#8221;&lt;br /&gt;&lt;br /&gt;I&amp;#8217;m not yet convinced that any hallway zombie is beyond reach, but there are a few here that are proving quite challenging.  I&amp;#8217;m working on some new attack strategies, just in case.  On the other hand, there have been some successes that are quite encouraging.  Slaying hallway zombies is hard work, but it&amp;#8217;s very rewarding.  So I keep fighting.&lt;br /&gt;&lt;br /&gt;You may not work in this type of environment, but chances are that you will find yourself somewhere, at some point in time, where you are faced with a hallway zombie.  Don&amp;#8217;t panic. Steady your nerves, hold your ground, and&amp;#8230; Smile!&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/73tRmhD2t6M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/5303801655070281284/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=5303801655070281284" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/5303801655070281284?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/5303801655070281284?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/73tRmhD2t6M/slaying-hallway-zombies.html" title="Slaying Hallway Zombies" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>4</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2009/11/slaying-hallway-zombies.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUBQno8fyp7ImA9WxNVF00.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-2495685724345004101</id><published>2009-10-27T19:23:00.000-07:00</published><updated>2009-10-27T20:57:33.477-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-27T20:57:33.477-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Conferences" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Spring" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Yet Another 2GX Wrap-up</title><content type="html">Finally after more than a year of waiting and &lt;a href="http://dave-klein.blogspot.com/2009/04/we-need-us-groovygrailsgriffon.html"&gt;nagging&lt;/a&gt;, the second 2GX conference was held in New Orleans last week.  It was almost as good as the first one.  Well, in some ways it was better but in other ways... well, we'll get to that in a bit.  But first, I wanted to say how great it was to see so many people from the Groovy community.  It is so cool to be able to put real faces to so many on-line friends.  I know conference people always say that "the attendees are what really makes the conference great", but as  a speaker and part-time staff member at this conference, I can say that it's really true.  The questions during the sessions and the discussions between sessions and at meals were the best part of the whole thing.  Even better than the Rod Johnson bobble-head dolls.  :-)&lt;br /&gt;&lt;br /&gt;Speaking of staff, I also want to tip my hat (if I had one) to the guys that pulled it all off.  Jay Zimmerman did as good of a job with the 500+ person event as he does with the &lt;a href="http://nofluffjuststuff.com/"&gt;NoFluffJustStuff&lt;/a&gt; conferences and his two volunteers (and one sales guy :), and my co-workers, &lt;a href="http://erik.weibust.net/"&gt;Erik Weibust&lt;/a&gt;, &lt;a href="http://twitter.com/twcrone"&gt;Todd Crone&lt;/a&gt;, and &lt;a href="http://www.linkedin.com/pub/paul-luttrell/1/210/a89"&gt;Paul Luttrell&lt;/a&gt; were tireless in their efforts to keep things running smoothly.  It was great working with you guys!&lt;br /&gt;&lt;br /&gt;One thing I want to highlight here was how excited I was to see some relative new comers  speaking at 2GX.  These guys aren't new to Groovy or Grails, but I think this was the first conference appearance for each of them and they were awesome!  &lt;a href="http://weblog.dangertree.net/"&gt;Matt Taylor&lt;/a&gt;, &lt;a href="http://hamletdarcy.blogspot.com/"&gt;Hamlet D'arcy&lt;/a&gt;, &lt;a href="http://refactr.com/blog/"&gt;Scott Vlaminck&lt;/a&gt; (the 'n' is silent), and &lt;a href="http://burtbeckwith.com/blog"&gt;Burt Beckwith&lt;/a&gt; (actually I'm not sure if Burt has spoken at other conferences, so forgive me if I'm wrong)&lt;br /&gt;&lt;br /&gt;Matt spoke on Grails UI, the YUI based Grails plugin that he developed and maintains as well as his experiences using Grails "in the wild".  I caught his GrailsUI talk and was very impressed, along with the rest of the room who all gave him the coveted "green cards".&lt;br /&gt;&lt;br /&gt;I didn't catch any of Hamlet's sessions but from what I heard from other attendees and on Twitter, he was a hit!  He gave four presentations altogether: OSGi and Groovy, Functional Groovy, Compiler Metaprogramming with AST transformations, and Legacy Code and Groovy. Rumor has it that he even had Venkat Subramaniam impressed.&lt;br /&gt;&lt;br /&gt;Scott Vlaminck, from &lt;a href="http://refactr.com/"&gt;Refactr&lt;/a&gt;, gave talks on Metaprogramming in Groovy and Grails, and AOP in Grails.  Again, I wasn't able to catch any of these talks in person, but the feedback was quite good and in fact I happened to be in the room next to one of Scott's talks and the speaker was almost drowned out by the applause!&lt;br /&gt;&lt;br /&gt;Burt also gave four presentations. He spoke on Spring Security in Grails, GORM performance, UI performance, and Clustering Grails apps.  I only caught the GORM performance talk, but it was one of my favorites.  I am already putting things I learned there to use in my day job. &lt;br /&gt;&lt;br /&gt;Of course the usual awesome Groovy/Grails/Griffon speakers were there and they were terrific as usual, but you've already heard about them and many others have or will blog about the cool Griffon sessions, or the Grails internals, or the power of Grails plugins, or the DSLs and Groovy testing magic, etc.  So I wanted to take a moment to congratulate these guys on a job well done.  I look forward to seeing them present at future events. &lt;br /&gt;&lt;br /&gt;Now, as to why I don't think this 2GX was quite as good as the first one.  The full name of the conference is a clue:  SpringOne 2GX.  SpringOne is a good conference, but 2GX is a great conference!  (or a GR8 conference :)  So, when combined we ended up with a more than good but not quite great conference.  Spring technology is cool.  Much of it (though not all) is behind some of the power of Grails.  And I do very much appreciate the support that SpringSource is giving to Groovy and Grails, but I think they just gave a bit of a "corporate feel" to the conference.&lt;br /&gt;&lt;br /&gt;I don't want to end on a downer though.  There were some distinct benefits of having the two events combined.  One was that SpringOne had some very good content and some exceptional speakers to add to the mix.  Another is that more than a few Spring users got to glimpse the goodness of Groovy, Grails and Griffon for the first time.  The oohs and ahhs were music to my ears!  It serves as a reminder to just be patient and hang in there... it's only a matter of time until they'll be holding the Groovy, Grails, Griffon and Spring conference!&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/kP6Vo0AzD-s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/2495685724345004101/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=2495685724345004101" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/2495685724345004101?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/2495685724345004101?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/kP6Vo0AzD-s/yet-another-2gx-wrap-up.html" title="Yet Another 2GX Wrap-up" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>0</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2009/10/yet-another-2gx-wrap-up.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cHR308eyp7ImA9WxNQEU8.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-8269886247500631082</id><published>2009-09-16T05:59:00.000-07:00</published><updated>2009-09-16T11:17:16.373-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-16T11:17:16.373-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NFJS" /><category scheme="http://www.blogger.com/atom/ns#" term="Griffon" /><category scheme="http://www.blogger.com/atom/ns#" term="Conferences" /><category scheme="http://www.blogger.com/atom/ns#" term="Groovy" /><category scheme="http://www.blogger.com/atom/ns#" term="Spring" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>10 Reasons to attend SpringOne 2GX</title><content type="html">I was going to come up with one of those clever top 10 lists but when I went to the SpringOne/2GX home page, I saw 10 great reasons to attend staring me in the face. &lt;br/&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Mt9WQBouLcM/SrDlLZCYj5I/AAAAAAAAAJY/X7J3qttv6KE/s1600-h/S12GX_Speakers.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 291px;" src="http://4.bp.blogspot.com/_Mt9WQBouLcM/SrDlLZCYj5I/AAAAAAAAAJY/X7J3qttv6KE/s400/S12GX_Speakers.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5382053538569949074" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;The early bird discount ends Friday, September 18th, but even at full price this event is less expensive than JavaOne and will contain way more good technical content. Check out the rest of the speakers and the awesome session list at &lt;a href="http://springone2gx.com"&gt;http://springone2gx.com&lt;/a&gt;&lt;br/&gt;&lt;br /&gt;If you're interested in Groovy, Grails, Griffon, (or related technologies) or if you use Spring in any of it's myriad forms, or, for that matter, if you use Java, you won't want to miss this conference!&lt;br/&gt;&lt;br /&gt;See you there!&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/d9DdeIZJ920" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/8269886247500631082/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=8269886247500631082" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/8269886247500631082?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/8269886247500631082?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/d9DdeIZJ920/10-reasons-to-attend-springone-2gx.html" title="10 Reasons to attend SpringOne 2GX" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_Mt9WQBouLcM/SrDlLZCYj5I/AAAAAAAAAJY/X7J3qttv6KE/s72-c/S12GX_Speakers.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2009/09/10-reasons-to-attend-springone-2gx.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMNRngyfCp7ImA9WxNTFU4.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-8207872244108229072</id><published>2009-08-17T09:37:00.001-07:00</published><updated>2009-08-17T10:34:57.694-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-17T10:34:57.694-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GQuick" /><category scheme="http://www.blogger.com/atom/ns#" term="GSP" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>New Blog for Grails: A Quick-Start Guide</title><content type="html">I'd like to announce a new blog for Grails:  A Quick-Start Guide.  You can find it at &lt;a href="http://gquick.blogspot.com/"&gt;http://gquick.blogspot.com&lt;/a&gt;.   In this blog, I'll continue to build on the example app in the book, and offer tips and techniques that didn't make it into the book.&lt;br /&gt;&lt;br /&gt;The first post covers displaying an image property of a domain class in a GSP.  In the GQuick example application, there is a Sponsor class that has a logo property.   We never had a chance to show how to properly render that logo image to a page in the book. &lt;br /&gt;&lt;br /&gt;If you've read the &lt;a href="http://pragprog.com/titles/dkgrails"&gt;beta of GQuick&lt;/a&gt; and have anything else you would like to see discussed, post a comment here, on gquick.blogspot.com, or at the &lt;a href="http://forums.pragprog.com/forums/116"&gt;book forum at pragprog.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I'd also like to take this opportunity to thank the beta ebook readers.  Your feedback has been a huge help!&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/VPEO1-RtULQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/8207872244108229072/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=8207872244108229072" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/8207872244108229072?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/8207872244108229072?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/VPEO1-RtULQ/new-blog-for-grails-quick-start-guide.html" title="New Blog for Grails: A Quick-Start Guide" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2009/08/new-blog-for-grails-quick-start-guide.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08CQXk7fSp7ImA9WxJaE0k.&quot;"><id>tag:blogger.com,1999:blog-7017083405558956091.post-1436219053902302482</id><published>2009-08-03T18:07:00.000-07:00</published><updated>2009-08-03T18:37:40.705-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-03T18:37:40.705-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Scala" /><category scheme="http://www.blogger.com/atom/ns#" term="Java.next" /><category scheme="http://www.blogger.com/atom/ns#" term="Clojure" /><category scheme="http://www.blogger.com/atom/ns#" term="Grails" /><title>Grails: The Official Web Framework for Java.next</title><content type="html">&lt;div&gt;In the August issue of &lt;a href="http://groovymag.com/"&gt;GroovyMag&lt;/a&gt;, guest plugin-corner columnist &lt;a href="http://www.linkedin.com/in/keithcochran"&gt;Keith Cochran&lt;/a&gt; covers the new Clojure plugin by &lt;a href="http://javajeff.blogspot.com/"&gt;Jeff Brown&lt;/a&gt;.  This plugin allows you to include Clojure source code in  src/clj and then access that code in your Grails application.   More details on the Clojure plugin can be found at &lt;a href="http://grails.org/plugin/clojure"&gt;http://grails.org/plugin/clojure&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A while back &lt;a href="http://www.jroller.com/vaclav"&gt;Vaclav Pech&lt;/a&gt; came out with a similar Grails plugin for Scala.  This one hasn't been covered in GroovyMag... yet.  Anyhow, you can find out more about this plugin at &lt;a href="http://grails.org/plugin/scala"&gt;http://grails.org/plugin/scala&lt;/a&gt;.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So now in a Grails application you can have Groovy code (all over the place), Scala code in src/scala, and Clojure code in src/clj.  That's pretty impressive!  As I was marveling at these recent developments, I realized that Grails now supports 3 out of the four languages covered in &lt;a href="http://blog.thinkrelevance.com/"&gt;Stu Halloway's&lt;/a&gt; paradigm-shifting blog series on &lt;a href="http://blog.thinkrelevance.com/2008/9/24/java-next-overview"&gt;Java.next&lt;/a&gt; (Groovy, Scala and Clojure - no JRuby... yet).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So unless something else comes along that as easily supports all four, I think we can safely call Grails the "Official Web Framework for Java.next". &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;P.S.  Lest I forget, &lt;a href="http://griffon.codehaus.org/"&gt;Griffon&lt;/a&gt; (the official Swing MVC framework for Java.next?) has quickly followed suit on supporting these languages.  &lt;a href="http://www.jroller.com/aalmiray/entry/griffon_gets_some_clojure"&gt;See Andres Almiray's blog for juicy details.&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;p&gt;
These cobblestones were kicked down by &lt;a href="http://dave-klein.blogspot.com/"&gt;Dave Klein&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/daveklein/~4/DckhOhPwMCI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://dave-klein.blogspot.com/feeds/1436219053902302482/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7017083405558956091&amp;postID=1436219053902302482" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/1436219053902302482?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7017083405558956091/posts/default/1436219053902302482?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/daveklein/~3/DckhOhPwMCI/grails-official-web-framework-for.html" title="Grails: The Official Web Framework for Java.next" /><author><name>Dave Klein</name><uri>http://www.blogger.com/profile/05996044798024907436</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://2.bp.blogspot.com/_Mt9WQBouLcM/SotTQs8iBKI/AAAAAAAAAIo/8Dp10iD-YLY/S220/dklein_avatar.png" /></author><thr:total>1</thr:total><feedburner:origLink>http://dave-klein.blogspot.com/2009/08/grails-official-web-framework-for.html</feedburner:origLink></entry></feed>
