<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><!-- generator="wordpress/2.0.1" --><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>SpencerUresk</title>
	<link>http://www.spenceruresk.com</link>
	<description>Random posts about Java, software development, politics, and economics</description>
	<pubDate>Tue, 07 Jul 2009 04:16:26 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.0.1</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/Spenceruresk" type="application/rss+xml" /><item>
		<title>Scala Job site + My experiences with Lift</title>
		<link>http://feedproxy.google.com/~r/Spenceruresk/~3/vL1T5jVV9yo/</link>
		<comments>http://www.spenceruresk.com/2009/07/06/scala-job-site-my-experiences-with-lift/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 04:16:26 +0000</pubDate>
		<dc:creator>suresk</dc:creator>
		
	<category>Technology</category>
	<category>Enterprise Development</category>
	<category>Websites</category>
	<category>Scala</category>
	<category>Lift</category>
		<guid isPermaLink="false">http://www.spenceruresk.com/2009/07/06/scala-job-site-my-experiences-with-lift/</guid>
		<description><![CDATA[I&#8217;ve played around with Scala off and on for over a year now, and also looked at Lift once or twice during that time. After going to David Pollak&#8217;s session at JavaOne about Lift, I decided to buckle down and actually create something with Scala and Lift, as I usually learn new things best by [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve played around with <a href="http://www.scala-lang.org">Scala</a> off and on for over a year now, and also looked at <a href="http://www.liftweb.net/">Lift</a> once or twice during that time. After going to David Pollak&#8217;s session at JavaOne about Lift, I decided to buckle down and actually create something with Scala and Lift, as I usually learn new things best by trying to create something useful. Looking around, I noticed there weren&#8217;t any Scala-specific job sites and thought it might be nice to create one.</p>
<p>The site is here: <a href="http://www.scalacareers.com/">ScalaCareers.com</a>, and you can follow on Twitter for announcements of new jobs posted and other things <a href="http://www.twitter.com/scalacareers">@scalacareers</a></p>
<p>In my opinion, jobs for a new language are extremely important in helping it get to the next level of adoption. Scala is already pretty popular and Lift is gaining in popularity, so I hope we start to see a lot more jobs that involve Scala and Lift.</p>
<p>I&#8217;m going to be posting some short tutorials and other things related to my experience in the coming weeks, but I thought I would share a few quick, high-level thoughts.</p>
<p>1) Lift is a solid, production-ready framework. I was able to learn enough of it to build a functional, albeit small, web application over the 4th of July weekend. Despite using a snapshot of the 1.1 release, I didn&#8217;t run into any bugs or severely out-of-date documentation.  I mention this because it has been a slight problem when I&#8217;ve been an early adopter of frameworks in the past.</p>
<p>2) The Lift community is incredibly friendly and helpful. Going back through several months of activity on the Google Group, they are generally accepting of criticism, quick to offer help, and even commit changes to the trunk quickly to help folks out. A good community is very important to newcomers to a new language or framework.</p>
<p>3) Using Lift requires a good knowledge of Scala to really be effective. Don&#8217;t get me wrong - learning Scala is well worth the effort - but it was a bit of a change for me, coming from Grails where I was able to sort of ease into it.</p>
<p>4) IDE support for Scala is still a little disappointing. Even though I love Groovy, I generally prefer static typed languages to dynamic typed ones, which is why I was interested in Scala in the first place. One of the big benefits of static typed languages is that you can theoretically get better IDE support. I shelled out a few hundred bucks for IntelliJ for this purpose, and while it was marginally better than the others, I still found lots of cases where auto-complete simply didn&#8217;t work and plenty more cases where it didn&#8217;t catch compile errors. It probably cost me a few hours on the project. A good IDE doesn&#8217;t make you a better developer, but it does make you faster :)</p>
<p>Overall, I think Scala and Lift have bright futures and are worth checking out.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://www.spenceruresk.com/2009/07/06/scala-job-site-my-experiences-with-lift/feed/</wfw:commentRSS>
		<feedburner:origLink>http://www.spenceruresk.com/2009/07/06/scala-job-site-my-experiences-with-lift/</feedburner:origLink></item>
		<item>
		<title>Bad API examples: java.util.Calendar</title>
		<link>http://feedproxy.google.com/~r/Spenceruresk/~3/Mdf3hyui5nk/</link>
		<comments>http://www.spenceruresk.com/2008/08/16/bad-api-examples-javautilcalendar/#comments</comments>
		<pubDate>Sat, 16 Aug 2008 22:28:33 +0000</pubDate>
		<dc:creator>suresk</dc:creator>
		
	<category>Uncategorized</category>
	<category>Software Development</category>
	<category>Java</category>
		<guid isPermaLink="false">http://www.spenceruresk.com/2008/08/16/bad-api-examples-javautilcalendar/</guid>
		<description><![CDATA[Take a look at the following code, and try to guess what is printed:

public static void main&#40;String&#91;&#93; args&#41; &#123;
&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; Date today = new Date&#40;&#41;;
&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; 
&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; Calendar c = new GregorianCalendar&#40;&#41;;
&#160; &#160; &#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p>Take a look at the following code, and try to guess what is printed:</p>
<div class="codesnip-container" >
<div class="codesnip"><span class="kw2">public</span> <span class="kw4">static</span> <span class="kw4">void</span> main<span class="br0">&#40;</span><a href="http://www.google.com/search?q=allinurl%3AString+java.sun.com&#038;bntl=1"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> args<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?q=allinurl%3ADate+java.sun.com&#038;bntl=1"><span class="kw3">Date</span></a> today = <span class="kw2">new</span> <a href="http://www.google.com/search?q=allinurl%3ADate+java.sun.com&#038;bntl=1"><span class="kw3">Date</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?q=allinurl%3ACalendar+java.sun.com&#038;bntl=1"><span class="kw3">Calendar</span></a> c = <span class="kw2">new</span> <a href="http://www.google.com/search?q=allinurl%3AGregorianCalendar+java.sun.com&#038;bntl=1"><span class="kw3">GregorianCalendar</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c.<span class="me1">add</span><span class="br0">&#40;</span><a href="http://www.google.com/search?q=allinurl%3ACalendar+java.sun.com&#038;bntl=1"><span class="kw3">Calendar</span></a>.<span class="me1">DAY_OF_YEAR</span>, <span class="nu0">10</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?q=allinurl%3ASystem+java.sun.com&#038;bntl=1"><span class="kw3">System</span></a>.<span class="me1">out</span>.<span class="me1">println</span><span class="br0">&#40;</span>c.<span class="me1">after</span><span class="br0">&#40;</span>today<span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</div>
<p>What is printed?</p>
<p>1. true<br />
2. false<br />
3. It doesn&#8217;t compile<br />
4. Runtime error</p>
<p>From a logical perspective, #1 is right - 10 days from now is after now, so you&#8217;d expect to see &#8216;true&#8217; printed. From a language perspective, you may think &#8220;you are passing in a java.util.Date to a function on java.util.Calendar, so it wouldn&#8217;t compile&#8221;, and choose #3. Neither of these are correct - the block of code above completes normally and prints &#8216;false&#8217;, which is not what we wanted.</p>
<p>If you take a look at the javadocs for <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/Calendar.html#after(java.lang.Object)">java.util.Calendar</a>, it is easy to see why. The signature for after (and before) is <em>public boolean after(Object when)</em>, but if you pass anything but a java.util.Calendar in, it will *always* return false. This is an unfortunate api design problem - it is reasonable to expect that you could pass in a java.util.Date, or even a long representing a timestamp to compare to the Calendar instance and it would work normally. The fact that either of those options compiles and runs without error can cover up the flaw in your code, and be difficult to track down (which is how I came across it and decided to write this post).</p>
<p>I am stumped trying to come up for a good reason for the method to accept Object (which means anything can be passed in - even primitives from Java 5 on) only to return false if it is anything other than java.util.Calendar. The method signature should be <em>public boolean after(java.util.Calendar when)</em>, so that you get a compile error instead of a silent failure at runtime. </p>
<p>Now, this library has been around since JDK 1.1, so I&#8217;m not exposing a new design flaw or anything. I am, however, curious as to how something so clearly anti-idiomatic Java (and anti-static typing) made it into a core Java library. Anyone have any ideas? The Date/Time APIs in Java are generally pretty bad anyway, but this seems especially poorly done.</p>
<p>I mostly write business code, and not much in the way of API code, but I have been reading the 2nd edition of Josh Bloch&#8217;s <a href="http://www.amazon.com/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.com%2FEffective-Java-2nd-Joshua-Bloch%2Fdp%2F0321356683%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1218919613%26sr%3D8-1&#038;tag=uresknetworks&#038;linkCode=ur2&#038;camp=1789&#038;creative=9325">Effective Java</a> and it has given me a better appreciation for the thought and effort that goes into creating useful APIs. It is always interesting to see some of the really good *and* really bad examples of API design in the core Java libraries.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://www.spenceruresk.com/2008/08/16/bad-api-examples-javautilcalendar/feed/</wfw:commentRSS>
		<feedburner:origLink>http://www.spenceruresk.com/2008/08/16/bad-api-examples-javautilcalendar/</feedburner:origLink></item>
		<item>
		<title>Quickly Redeploying Grails Apps</title>
		<link>http://feedproxy.google.com/~r/Spenceruresk/~3/M0GOTnqQ1C8/</link>
		<comments>http://www.spenceruresk.com/2008/07/02/quickly-redeploying-grails-apps/#comments</comments>
		<pubDate>Wed, 02 Jul 2008 06:30:53 +0000</pubDate>
		<dc:creator>suresk</dc:creator>
		
	<category>Software Development</category>
	<category>Websites</category>
	<category>Groovy</category>
	<category>Grails</category>
		<guid isPermaLink="false">http://www.spenceruresk.com/2008/07/02/quickly-redeploying-grails-apps/</guid>
		<description><![CDATA[I&#8217;ve been developing a bunch of small Grails apps lately, and I end up deploying them to my production box fairly frequently. This is kind of annoying because the upload speed on my home internet connection is terrible - it sometimes takes 7 or 8 minutes to upload a new WAR and during that time, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been developing a bunch of small Grails apps lately, and I end up deploying them to my production box fairly frequently. This is kind of annoying because the upload speed on my home internet connection is terrible - it sometimes takes 7 or 8 minutes to upload a new WAR and during that time, my internet connection is unusable for anything else. I wanted a simple way to push new code to production without uploading a new WAR every time, and I know a few other people were looking for something similar, so here it is. It is pretty boring but it does the job. In my case, I deploy all of mine as ROOT.war, because they are always the default app for their domain. If yours is setup different, just replace ROOT.war with whatever your war should be named.</p>
<p>1. Check your code into Subversion (or CVS or whatever SCM of your choice - this guide assumes Subversion, however).</p>
<p>2. Add a build directory on your prod box (I have mine at /home/build/) - then check out individual projects under it (ie, /home/build/wiifit/).</p>
<p>3. In each project, add a property to application.properties for the deployment directory (ie - deploy.dir=/home/tc6/server/wiifit).</p>
<p>4. In grails, you can add groovy scripts to the /scripts/ directory, and then run them with grails <script-name>, ie, ProdPush.groovy can be called with &#8216;grails prod-push&#8217;. Let&#8217;s add a script in to do the following things:</p>
<p>- Do a subversion checkout to get our latest changes.<br />
- Build the war<br />
- Copy it to our directory</p>
<p>This is what I came up with:</p>
<div class="codesnip-container" >
<div class="codesnip">grailsHome = Ant.<span class="me1">project</span>.<span class="me1">properties</span>.<span class="st0">&#8220;environment.GRAILS_HOME&#8221;</span></p>
<p>includeTargets &lt;&lt; <span class="kw2">new</span> <a href="http://www.google.com/search?q=allinurl%3AFile+java.sun.com&#038;bntl=1"><span class="kw3">File</span></a> <span class="br0">&#40;</span> <span class="st0">&#8220;${grailsHome}/scripts/War.groovy&#8221;</span><span class="br0">&#41;</span></p>
<p>target<span class="br0">&#40;</span><span class="st0">&#8216;default&#8217;</span>: <span class="st0">&#8220;Push a war to prod&#8221;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;println <span class="st0">&#8220;svn up&#8221;</span>.<span class="me1">execute</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">text</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;war<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;Ant.<span class="me1">copy</span><span class="br0">&#40;</span>todir:Ant.<span class="me1">antProject</span>.<span class="me1">properties</span>.<span class="st0">&#8216;deploy.dir&#8217;</span>, overwrite:<span class="kw2">true</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fileset<span class="br0">&#40;</span>dir:<span class="st0">&#8220;.&#8221;</span>, includes:<span class="st0">&#8220;ROOT.war&#8221;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>Your script can have multiple targets. If you specify a &#8216;default&#8217; one, like I have above, it is what will be run if you supply no target (which is what we want).</p>
<p>5. Now I have a simple shell script on my server to setup the environment variables and run the build.</p>
<div class="codesnip-container" >
<div class="codesnip"><span class="co1">#!/bin/bash</span></p>
<p><span class="kw3">export</span> <span class="re2">GROOVY_HOME=</span>/usr/share/groovy<br />
<span class="kw3">export</span> <span class="re2">GRAIILS_HOME=</span>/usr/share/grails<br />
<span class="kw3">export</span> <span class="re2">JAVA_HOME=</span>/usr/java/jdk<br />
<span class="kw3">export</span> <span class="re2">GWT_HOME=</span>/usr/share/gwt</p>
<p><span class="kw3">cd</span> $<span class="nu0">1</span></p>
<p><span class="re1">$GRAILS_HOME</span>/bin/grails -Dgrails.<span class="re2">env=</span>production prod-push ROOT.war</div>
</div>
<p>This script can then be re-used for all projects on the server.</p>
<p>6. To update our app, we simply do the following:</p>
<p>- Check our changes into Subversion<br />
- SSH into our server and go to our /build/ directory<br />
- Run the build script (ie, ./build.sh wiifit)</p>
<p>Our new app is live in less than a minute and we don&#8217;t kill our home internet connection :)</p>
<p>This solution may not be very good for high-usage, critical apps - if I were building (and leaving code) on a production app server at my day job, I&#8217;d be fired (and deserve it!) - but for small apps like I build, it is a good solution. This solution is pretty simple, but I&#8217;m working on a full deployment plugin for grails - fewer setup steps, tomcat management, etc.. If you have any suggestions or ideas, let me know.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://www.spenceruresk.com/2008/07/02/quickly-redeploying-grails-apps/feed/</wfw:commentRSS>
		<feedburner:origLink>http://www.spenceruresk.com/2008/07/02/quickly-redeploying-grails-apps/</feedburner:origLink></item>
		<item>
		<title>Grails + GWT with GWT-EXT + GoogleMaps + MaxMind sample application</title>
		<link>http://feedproxy.google.com/~r/Spenceruresk/~3/ydQC-rhvISY/</link>
		<comments>http://www.spenceruresk.com/2008/06/15/grails-gwt-with-gwt-ext-googlemaps-maxmind-sample-application/#comments</comments>
		<pubDate>Sun, 15 Jun 2008 06:04:38 +0000</pubDate>
		<dc:creator>suresk</dc:creator>
		
	<category>Software Development</category>
	<category>Java</category>
	<category>Groovy</category>
	<category>Grails</category>
	<category>GWT</category>
		<guid isPermaLink="false">http://www.spenceruresk.com/2008/06/15/grails-gwt-with-gwt-ext-googlemaps-maxmind-sample-application/</guid>
		<description><![CDATA[I&#8217;ve been playing around with Grails and a bit of GWT lately, and it sure is a lot of fun. I&#8217;ve made some applications that use Grails, GWT, and GoogleMaps (see: Find A Wii Fit), and thought I&#8217;d write a quick tutorial on how to do it - it can be a little tricky.
This application [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been playing around with Grails and a bit of GWT lately, and it sure is a lot of fun. I&#8217;ve made some applications that use <a href="http://www.grails.org/">Grails</a>, <a href="http://code.google.com/webtoolkit/">GWT</a>, and <a href="http://code.google.com/apis/maps/">GoogleMaps</a> (see: <a href="http://www.findawiifit.com/site/map">Find A Wii Fit</a>), and thought I&#8217;d write a quick tutorial on how to do it - it can be a little tricky.</p>
<p>This application is fairly simple - it displays a google map view that is centered on the user&#8217;s location, and inserts a marker where they are located. I am using <a href="http://www.maxmind.com/?rId=uresk">MaxMind</a> to turn an IP into latitude and longitude coordinates. They cost money and you may be able to find a free one, but they aren&#8217;t that expensive (something like $20 for 50,000 lookups) and I&#8217;ve been pretty happy with them so far.</p>
<p>There is a <a href="http://www.grails.org/GWT+Plugin">GWT+Grails</a> plugin that makes it easy for Grails and GWT to work together. I am also using <a href="http://gwt-ext.com/">GWT-EXT</a> to make it look nice, and to make the GoogleMaps integration a little easier. If you want to see this app in action, you can see it <a href="http://www.maptutorials.com/">here</a> (it may not match the example exactly - I&#8217;m actively developing it). I&#8217;ve also made the entire project available for free, <a href="http://www.spenceruresk.com/findme.zip">here</a>.</p>
<p>1.Create a new Grails application (grails create-app findme)</p>
<p>2.Install the Grails + GWT plugin (grails install-plugin gwt)</p>
<p>3.Create your Grails Module (grails create-gwt-module net.uresk.FindMe)</p>
<p>4. Create your page (grails create-gwt-page main/index.gsp net.uresk.FindMe, answer yes when it asks if you want it to create the controller)</p>
<p>5. Download GWT-EXT (<a href="http://gwt-ext.com/download/">http://gwt-ext.com/download/</a>), put gwtext.jar in your project’s lib/gwt directory (ie, $PROJECT_NAME/lib/gwt). You’ll also have to put it into the plugins/gwt-0.2.4/lib directory.</p>
<p>6. We&#8217;ll then have to hack _Internal in the /plugins/gwt-0.2.4/scripts/ directory (hopefully this won&#8217;t be necessary in the next version of the plugin). Around line 89, you&#8217;ll have to add in another include entry after the others:</p>
<p>Include(name: &#8216;gwtext.jar&#8217;);</p>
<p>We&#8217;ll also need to go down a few more lines, and before &#8216;pathElement(location: &#8220;${basedir}/${srcDir}&#8221;)&#8217;, add &#8216;pathElement(location: &#8220;${basedir}/lib/gwt/gwtext.jar&#8221;)&#8217;.</p>
<p>Lastly, if you get an error about heap space, you&#8217;ll need to give the gwt compiler more heap space. Do this by adding in &#8216;jvmarg(value: &#8216;-Xmx256M&#8217;)&#8217; a few lines down (around line 102), just above where the other arg() lines start. Not sure if this is related to using gwt-ext, running on Mac OS X, or what, but I did run into it a few times.</p>
<p>7. Download EXT 2.0.2 (<a href="http://yogurtearl.com/ext-2.0.2.zip">http://yogurtearl.com/ext-2.0.2.zip</a>), copy the &#8216;adapter&#8217; and &#8216;resources&#8217; directory, along with the &#8216;ext-all.js&#8217;, &#8216;ext-all-debug.js&#8217;, &#8216;ext-core.js&#8217;,  and &#8216;ext-core-debug.js&#8217; into your project&#8217;s /web-app/js/ directory.</p>
<p>8. Download mapstraction (<a href="http://mapstraction.com/svn/source/mapstraction.js">http://mapstraction.com/svn/source/mapstraction.js</a>) and copy it into your applications web-app/js directory as well.</p>
<p>9. Open up your Grails project (I prefer IntelliJ for Groovy/Grails development at the moment, btw) and find the FindMe.gwt.xml file (it is in /src/java/net/uresk directory). Add in the following:</p>
<pre>
<div class="codesnip-container" >
<div class="codesnip"><span class="sc2">&lt;inherits <span class="kw3">name</span>=<span class="st0">&#8220;com.gwtext.GwtExt&#8221;</span> /<span class="kw2">&gt;</span></a></span>
<span class="sc2">&lt;stylesheet <span class="kw3">src</span>=<span class="st0">&#8220;/findme/js/resources/css/ext-all.css&#8221;</span> /<span class="kw2">&gt;</span></a></span>
<span class="sc2"><a href="http://december.com/html/4/element/script.html"><span class="kw2">&lt;script</span></a> <span class="kw3">src</span>=<span class="st0">&#8220;/findme/js/adapter/ext/ext-base.js&#8221;</span> /<span class="kw2">&gt;</span></a></span>
<span class="sc2"><a href="http://december.com/html/4/element/script.html"><span class="kw2">&lt;script</span></a> <span class="kw3">src</span>=<span class="st0">&#8220;/findme/js/ext-all.js&#8221;</span> /<span class="kw2">&gt;</span></a></span></div>
</div>
</pre>
<p>10. Add the following entries in:<br />
Create your Google Maps keys for localhost and for your production domain. To make things easy, I added a config property in called &#8216;googlemaps.key&#8217;, and then added this into my controller to get it for the right environment:[key: grailsApplication.config.googlemaps.key]12. In your index.gsp, add in the following:</p>
<p>A reference to mapstraction: &lt;script type=&#8221;text/javascript&#8221; src=&#8221;/findme/js/map/mapstraction.js&#8221;&gt;&lt;/script></pre>
<p>The google maps js include: &lt;script type=&#8221;text/javascript&#8221; src=&#8221;http://maps.google.com/maps?file=api&#038;v=2.x&#038;key=${key}&#8221;&gt;&lt;/script&gt;</pre>
<p>13. Now create a service called something like LookupService, and add in the following code to access MaxMind:</p>
<pre>
<div class="codesnip-container" >
<div class="codesnip"><span class="kw2">class</span> LookupService <span class="br0">&#123;</span>

&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> expose = <span class="br0">&#91;</span><span class="st0">&#8216;gwt:net.uresk.client&#8217;</span><span class="br0">&#93;</span>

&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?q=allinurl%3ADouble+java.sun.com&#038;bntl=1"><span class="kw3">Double</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> getLatLonFromIp<span class="br0">&#40;</span><a href="http://www.google.com/search?q=allinurl%3AString+java.sun.com&#038;bntl=1"><span class="kw3">String</span></a> ip<span class="br0">&#41;</span><span class="br0">&#123;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>!<span class="br0">&#40;</span>ip ==~ /bd<span class="br0">&#123;</span><span class="nu0">1</span>,<span class="nu0">3</span><span class="br0">&#125;</span>.d<span class="br0">&#123;</span><span class="nu0">1</span>,<span class="nu0">3</span><span class="br0">&#125;</span>.d<span class="br0">&#123;</span><span class="nu0">1</span>,<span class="nu0">3</span><span class="br0">&#125;</span>.d<span class="br0">&#123;</span><span class="nu0">1</span>,<span class="nu0">3</span><span class="br0">&#125;</span>b/<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ip = defaultIp
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; def res = <span class="st0">&#8220;http://geoip1.maxmind.com/b?l=${maxMindKey}&amp;i=${ip}&#8221;</span>.<span class="me1">toURL</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">text</span>.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&#8220;,&#8221;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?q=allinurl%3ADouble+java.sun.com&#038;bntl=1"><span class="kw3">Double</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> result = <span class="kw2">new</span> <a href="http://www.google.com/search?q=allinurl%3ADouble+java.sun.com&#038;bntl=1"><span class="kw3">Double</span></a><span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> = <a href="http://www.google.com/search?q=allinurl%3ADouble+java.sun.com&#038;bntl=1"><span class="kw3">Double</span></a>.<span class="me1">parseDouble</span><span class="br0">&#40;</span>res<span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> = <a href="http://www.google.com/search?q=allinurl%3ADouble+java.sun.com&#038;bntl=1"><span class="kw3">Double</span></a>.<span class="me1">parseDouble</span><span class="br0">&#40;</span>res<span class="br0">&#91;</span><span class="nu0">4</span><span class="br0">&#93;</span><span class="br0">&#41;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">return</span> result
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>
<span class="br0">&#125;</span></div>
</div>
</pre>
<p>You can swap out <a href="http://www.maxmind.com/?rId=uresk">MaxMind</a> with any other service. I added a maxMindKey config property in Config.groovy, but you can easily hard-code it.</p>
<p>14. Now create your GWT client code, something like this:</p>
<pre>
<div class="codesnip-container" >
<div class="codesnip">GoogleMap mainPanel;

&nbsp; &nbsp; <span class="coMULTI">/**
&nbsp; &nbsp; &nbsp;* This is the entry point method.
&nbsp; &nbsp; &nbsp;*/</span>
&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw4">void</span> onModuleLoad<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; createPanel<span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;<span class="kw2">new</span> Viewport<span class="br0">&#40;</span>mainPanel<span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;updateLatLonFromMaxMind<span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; <span class="br0">&#125;</span>

&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="kw4">void</span> updateLatLonFromMaxMind<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LookupServiceAsync myService = <span class="br0">&#40;</span>LookupServiceAsync<span class="br0">&#41;</span> GWT.<span class="me1">create</span><span class="br0">&#40;</span>LookupService.<span class="kw2">class</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ServiceDefTarget endpoint = <span class="br0">&#40;</span>ServiceDefTarget<span class="br0">&#41;</span> myService;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?q=allinurl%3AString+java.sun.com&#038;bntl=1"><span class="kw3">String</span></a> moduleRelativeURL = GWT.<span class="me1">getModuleBaseURL</span><span class="br0">&#40;</span><span class="br0">&#41;</span> + <span class="st0">&#8220;rpc&#8221;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; endpoint.<span class="me1">setServiceEntryPoint</span><span class="br0">&#40;</span>moduleRelativeURL<span class="br0">&#41;</span>;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AsyncCallback callback = <span class="kw2">new</span> AsyncCallback<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw4">void</span> onSuccess<span class="br0">&#40;</span><a href="http://www.google.com/search?q=allinurl%3AObject+java.sun.com&#038;bntl=1"><span class="kw3">Object</span></a> result<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;<a href="http://www.google.com/search?q=allinurl%3ADouble+java.sun.com&#038;bntl=1"><span class="kw3">Double</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> latLon = <span class="br0">&#40;</span><a href="http://www.google.com/search?q=allinurl%3ADouble+java.sun.com&#038;bntl=1"><span class="kw3">Double</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>result;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setLatLong<span class="br0">&#40;</span>latLon<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>, latLon<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span>

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">public</span> <span class="kw4">void</span> onFailure<span class="br0">&#40;</span><a href="http://www.google.com/search?q=allinurl%3AThrowable+java.sun.com&#038;bntl=1"><span class="kw3">Throwable</span></a> caught<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;<span class="co1">// do some UI stuff to show failure</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; myService.<span class="me1">getLatLonFromIp</span><span class="br0">&#40;</span>callback<span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>

&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="kw4">void</span> setLatLong<span class="br0">&#40;</span><a href="http://www.google.com/search?q=allinurl%3ADouble+java.sun.com&#038;bntl=1"><span class="kw3">Double</span></a> lat, <a href="http://www.google.com/search?q=allinurl%3ADouble+java.sun.com&#038;bntl=1"><span class="kw3">Double</span></a> lon<span class="br0">&#41;</span><span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LatLonPoint llp = <span class="kw2">new</span> LatLonPoint<span class="br0">&#40;</span>lat.<span class="me1">doubleValue</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, lon.<span class="me1">doubleValue</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Marker m = <span class="kw2">new</span> Marker<span class="br0">&#40;</span>llp<span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m.<span class="me1">setInfoBubble</span><span class="br0">&#40;</span><span class="st0">&#8220;&lt;div&gt;You are here!&lt;/div&gt;&#8221;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mainPanel.<span class="me1">setCenterAndZoom</span><span class="br0">&#40;</span>llp, <span class="nu0">10</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mainPanel.<span class="me1">addMarker</span><span class="br0">&#40;</span>m<span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span>

&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="kw4">void</span> createPanel<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mainPanel = <span class="kw2">new</span> GoogleMap<span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mainPanel.<span class="me1">setTitle</span><span class="br0">&#40;</span><span class="st0">&#8220;Spencer&#8217;s Google Map Page&#8221;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mainPanel.<span class="me1">addLargeControls</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</div>
</pre>
<p>15. Now, we need to create the stubs for this service so that GWT can use it. Do this by running &#8216;grails run-app&#8217;.</p>
<p>16. Unfortunately, there currently isn&#8217;t an easy way to get at the HttpRequest object inside our service. There is a <a href="http://jira.codehaus.org/browse/GRAILSPLUGINS-386">JIRA item</a> open for this, and I&#8217;m working on a potential solution. In the meantime, we’ll have to do a bit of hacking.</p>
<p>First, we&#8217;ll need to open up the LookupService and LookupServiceAsync java files that the plugin generated – they are in /src/net/uresk/client in this example. Modify the method signatures so they don’t take a String object (the IP). They should look like: java.lang.Double[] getLatLonFromIp(); and void getLatLonFromIp(AsyncCallback callback);</p>
<p>Next, we&#8217;ll need to modify the GrailsRemoteServiceServlet (in /plugins/gwt-0.2.4/src/groovy/org/codehaus/groovy/grails/plugins/gwt). On line 53, we are going to modify the method call so that it explicitly passes in the ip address, by changing it to say this:</p>
<p>def retval = service.invokeMethod(serviceMethod.name, this.getThreadLocalRequest().getRemoteAddr())</p>
<p>If you are using this behind a proxy (ie, behind Apache HTTPD with mod_proxy), getRemoteAddr() won&#8217;t work – you&#8217;ll have to instead get the X-Forwarded-For header value.</p>
<p>This is a nasty hack, and will break all your other GWT RPC calls, so if you are going to do more with this example, you&#8217;ll have to do something a little smarter to inject the IP (contact me if you want some ideas, and also keep an eye on the JIRA item mentioned above). Hopefully it won&#8217;t be necessary much longer.</p>
<p>You should be able to run your application now! Do &#8216;grails run-app&#8217; again and browse to <a mce_href="http://localhost:8080/findme/main" xhref="http://localhost:8080/findme/main">http://localhost:8080/findme/main</a>.</p>
<p>Let me know if you have any questions or suggestions. I also hang out on the #groovy IRC channel on the evenings and weekends (GMT -700) if you need help.</p>
<p>Have fun :)</p>
<p>Special Thanks to <a href="http://abhijeetmaharana.com/blog/2008/04/07/gwt-ext-and-google-maps/">Abhijeet Maharana</a> who provided an excellent how-to for using GoogleMaps with Gwt-Ext.</p>
<p><b>Update:</b> Sorry, I forgot to include the GWT client code in the original post. It is in there, step 14 now. Let me know if I missed anything else.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://www.spenceruresk.com/2008/06/15/grails-gwt-with-gwt-ext-googlemaps-maxmind-sample-application/feed/</wfw:commentRSS>
		<feedburner:origLink>http://www.spenceruresk.com/2008/06/15/grails-gwt-with-gwt-ext-googlemaps-maxmind-sample-application/</feedburner:origLink></item>
		<item>
		<title>Running Grails applications on a VPS</title>
		<link>http://feedproxy.google.com/~r/Spenceruresk/~3/XwnFAkQHRWY/</link>
		<comments>http://www.spenceruresk.com/2008/06/12/running-grails-applications-on-a-vps/#comments</comments>
		<pubDate>Fri, 13 Jun 2008 04:02:49 +0000</pubDate>
		<dc:creator>suresk</dc:creator>
		
	<category>Technology</category>
	<category>Enterprise Development</category>
	<category>Websites</category>
	<category>Groovy</category>
	<category>Grails</category>
		<guid isPermaLink="false">http://www.spenceruresk.com/2008/06/12/running-grails-applications-on-a-vps/</guid>
		<description><![CDATA[For some time, it has been one of my dreams to see Java-based web applications be more viable for small websites. This means two things: rapid development capabilities (like Ruby on Rails), and inexpensive, reliable, and economical hosting options.
For goal #1, Grails is clearly fitting the bill. I spent the last year or so developing [...]]]></description>
			<content:encoded><![CDATA[<p>For some time, it has been one of my dreams to see Java-based web applications be more viable for small websites. This means two things: rapid development capabilities (like Ruby on Rails), and inexpensive, reliable, and economical hosting options.</p>
<p>For goal #1, <a href="http://www.grails.org/">Grails</a> is clearly fitting the bill. I spent the last year or so developing Rails apps, and Grails feels almost as productive. The community around it is getting quite active and there are some excellent plugins.</p>
<p>Reaching Goal #2 is going to be a bit trickier, but I think we are getting close. I am able to deploy 3 or 4 Grails applications on a 256 MB VPS now, and they work reasonably well. The good thing is that VPS&#8217; are getting quite cheap, and a VPS with 256 MB of memory can easily be had for less than $20/month. (Shameless plug - I am putting together a site - <a href="http://www.vps-hosting-reviews.com/">VPS hosting reviews</a> - that lists vps providers, their plans, prices, and reviews. And it is developed with Grails and running on a VPS :) )That said, you wouldn&#8217;t want to do this if your applications get a ton of traffic, and hosting a Java application will never be as cheap as hosting PHP applications.</p>
<p>Getting several Grails/Java applictions deployed on a server with only 256 MB of RAM (and on a VPS, no less, where getting a big block of contiguous memory can be tricky) takes a bit of work, so I&#8217;ve decided to detail a few things I&#8217;ve learned. This is specifically for Grails applications, although most of the tips should be helpful for any other Java application deployment as well. It also assumes you are using Tomcat as your app server.</p>
<p><strong>1. Dump Apache HTTP server</strong></p>
<p>A lot of people (including me for the longest time) would use Apache to forward requests to Tomcat. There is nothing wrong with Apache HTTP server itself, but in this setup, it can eat up a bunch of memory and really isn&#8217;t necessary. You can use iptables or xinetd to forward requests from port 80 to your app server. A good tutorial for these options can be found <a href="http://www.ibm.com/developerworks/linux/library/l-secjav.html">here</a>. Doing this should free up a bit more precious memory for your app server.</p>
<p><strong>2. Make sure you are using the server JVM</strong></p>
<p>This is easy to forget to do - HotSpot will automatically choose which vm to run based on server attributes, so on a real production box, it will choose the server vm automatically. On a VPS, you&#8217;ll need to manually do this by adding &#8220;-server&#8221; to CATALINA_OPTS.</p>
<p><strong>3. Give you server more PermGen space</strong></p>
<p>Groovy uses a bit more PermGen space than normal, due to all the classloading it does. This means you&#8217;ll probably want to configure your vm to use a bit more PermGen space than usual by doing -XX:MaxPermSize=m. On my server, setting this to about half of the overall memory allocated seemed to be the best, but your results may vary.</p>
<p><strong>4. Experiment</strong></p>
<p>Ideally, you&#8217;d just upload your apps and not worry about tuning, but when you are trying to squeeze the most out of a VPS, this isn&#8217;t the case. Play around with different memory settings and other vm options to see what gets your particular setup the best performance and stability. Feel free to share what works well for you :)
</p>
]]></content:encoded>
			<wfw:commentRSS>http://www.spenceruresk.com/2008/06/12/running-grails-applications-on-a-vps/feed/</wfw:commentRSS>
		<feedburner:origLink>http://www.spenceruresk.com/2008/06/12/running-grails-applications-on-a-vps/</feedburner:origLink></item>
		<item>
		<title>Avoiding unpleasant code with peer reviews</title>
		<link>http://feedproxy.google.com/~r/Spenceruresk/~3/s7Nak7JVI9M/</link>
		<comments>http://www.spenceruresk.com/2008/05/26/avoiding-unpleasant-code-with-peer-reviews/#comments</comments>
		<pubDate>Mon, 26 May 2008 23:07:20 +0000</pubDate>
		<dc:creator>suresk</dc:creator>
		
	<category>Technology</category>
	<category>Enterprise Development</category>
	<category>Software Development</category>
		<guid isPermaLink="false">http://www.spenceruresk.com/2008/05/26/avoiding-unpleasant-code-with-peer-reviews/</guid>
		<description><![CDATA[
Ah, the smell of a fresh codebase.
I’m certain most software developers who have been around for any amount of time have had to work on “The Project”. This project has probably been going for years, has had a fair amount of turnover on the development team, and has had a handful of architects (with their [...]]]></description>
			<content:encoded><![CDATA[<div class="Section1">
<p class="MsoNormal">Ah, the smell of a fresh codebase.</p>
<p class="MsoNormal">I’m certain most software developers who have been around for any amount of time have had to work on “The Project”. This project has probably been going for years, has had a fair amount of turnover on the development team, and has had a handful of architects (with their own way of doing things).</p>
<p class="MsoNormal">Projects like this may work wonderfully and be very successful from a business standpoint, and the individuals working on them are likely quite competent. Yet, from a development perspective, they are a nightmare. They contain difficult to understand code, lots of unused (or commented out) code, little testing, little adherence to good development practices, few comments, and a general feeling of brittleness.</p>
<p class="MsoNormal">Code like this may work exactly as intended, but when a codebase gets disorganized, chaotic, and sloppy it can lead to other problems, such as:</p>
<ul>
<li><!--[if !supportLists]--><span />An unpleasant experience for developers</li>
</ul>
<ul>
<li><!--[if !supportLists]--><span />High cost to refactor code</li>
</ul>
<ul>
<li><!--[if !supportLists]--><span />More bugs</li>
</ul>
<p class="MsoNormal">I’ve worked on a few projects like this over the last 5 years or so, and was naturally excited when I found we were going to be starting with a fresh codebase. At last, all of this cruft that has accumulated over the half a decade this project has been going will no more!</p>
<p class="MsoNormal">Imagine my surprise (and dismay) a month after the new project started when I found most of the symptoms of “The Project” starting to present themselves in the new codebase. Looking through our project and the reports we generate (PMD, CPD, Clover), I saw:</p>
<ul>
<li><!--[if !supportLists]--><span />Lots of untested code</li>
</ul>
<ul>
<li><!--[if !supportLists]--><span />Lots of bad practices and sloppy coding (as shown by PMD – we really pared down the ruleset so we don’t get a ton of false positives)</li>
</ul>
<ul>
<li><!--[if !supportLists]--><span />Unused code (already, after less than a month!?)</li>
</ul>
<ul>
<li><!--[if !supportLists]--><span />Commented-out code</li>
</ul>
<ul>
<li><!--[if !supportLists]--><span />Methods that were too big, hard to understand, or uncommented</li>
</ul>
<p class="MsoNormal">Part of this was due to spikes being done for the new project, which led me to conclude that spikes or experimental work of any kind should always be done in a branch. I also became interested in how code gets to this state so quickly, and of far more importance, how to keep it from reaching this state.</p>
<p class="MsoNormal">I don’t think this happens because people are bad developers necessarily, but because it requires a large degree of diligence and policing to keep a codebase clean and well-organized. It is easy to let organizational or quality issues fall to the wayside when working on functionality, and timelines sometimes leave little time for these tasks.</p>
<p class="MsoNormal">Some people offer up pair programming as a way to avoid this, but I don’t particular care for it (see my comments on <a href="http://www.spenceruresk.com/2007/03/25/impaired-programming-how-neither-of-us-is-as-dumb-as-both-of-us/">pair programming</a>). I think situational pair programming is an excellent practice, but I think full-time pair programming is, besides a terrible waste of time, largely ineffective.</p>
<p class="MsoNormal">After doing some research and analysis of how we work, I’m beginning to think that peer reviews are an excellent solution and practice. They provide most of the benefits of pair programming with few of the drawbacks. You still have someone examining your code, asking questions, and offering feedback, but instead of doing it for an entire iteration or whatever (where one of you will likely be bored for a good portion of the time), you do it for an hour or whatever is necessary. The only potential drawback is that if someone is totally off on their approach and it isn’t noticed until the end, it could be costly to refactor (so costly, in some cases, that it may be left in its sub-optimal state).</p>
<p class="MsoNormal">With that in mind, I set out to attempt to come up with good practices for conducting code reviews, and also best practices we should be following to keep our codebase clean and easy to work with. I’m wondering what other organizations are doing for peer reviews, and what I can do to improve the stuff I came up with.</p>
<p class="MsoNormal">It should be noted that a peer review is largely orthogonal from a QA review – a particular block of work can pass the QA review with flying colors and totally fail the peer review. The way I see it, QA reviews inspect the interface, peer reviews inspect the implementation.</p>
<p class="MsoNormal">Here is the document I came up with:</p>
<p class="MsoNormal">&#8211;</p>
<p class="MsoNormal">The peer review should occur prior to resolving a story or bug. At least 30 minutes should be set aside for a peer review, to allow for a thorough review. Once the review has been completed and the reviewer is satisfied, they should leave a comment on the JIRA entry stating that they have peer reviewed the unit of work.</p>
<p class="MsoNormal">Besides following this checklist, you both should go over all the code you wrote for this story. The reviewer should not hesitate to point out how something could have been done in a better way. If the reviewer cannot figure out what a particular piece of code does in a relatively short amount of time, it should be re-written or comments should be added in the code.</p>
<p class="MsoNormal"><strong>1. Metrics / Standards </strong></p>
<p class="MsoNormal">- (<span style="font-size: 11pt; line-height: 115%; font-family: "Calibri","sans-serif"">any coding metrics – code coverage, static analysis, etc)</span></p>
<p class="MsoNormal">- Test coverage should be meaningful – ie, don’t just check that a method executed without throwing an exception</p>
<p class="MsoNormal">- Use the right kind of test for your code (ie, some code may need just unit tests, others may need integration tests, and some might need functional tests)</p>
<p class="MsoNormal">- Business logic is properly tested with unit tests</p>
<p class="MsoNormal">- If this is a bug, was a unit test specifically for that bug created?</p>
<p class="MsoNormal"><strong>2. Code Style </strong></p>
<p class="MsoNormal">- Properly formatted Java code</p>
<p class="MsoNormal">- No commented-out code</p>
<p class="MsoNormal">- No unused code</p>
<p class="MsoNormal">- JPA standards followed (we have a separate document for this)</p>
<p class="MsoNormal">- If you have to explain a piece of code to your reviewer, that piece of code should be documented</p>
<p class="MsoNormal">- If your code is meant to be re-used throughout the app (ie, a utility class) it should have descriptive and useful JavaDocs</p>
<p class="MsoNormal">- Classes should be fewer than 500 lines of code, and any over 250 lines should be scrutinized closely</p>
<p class="MsoNormal"><strong>3. View </strong></p>
<p class="MsoNormal">- All JSF controls have explicit ids</p>
<p class="MsoNormal">- Everything works in IE (firefox support is strongly recommended, as well)</p>
</div>
<p class="MsoNormal">- All fields validate properly (ie, no 500 errors when you put in invalid values)</p>
<p class="MsoNormal">- JSF pages named consistently</p>
<p class="MsoNormal">&#8211;</p>
<p class="MsoNormal">This is part policing – making sure people are following best practices we’ve set forth, and that part of it kind of sucks. It is also part informative, however. Ideally, both the reviewer and the developer are learning from the experience. The reviewer may see a way to do something better and thereby make the code better and increase the skill of the developer. The reviewer may also see something that educates them as well.</p>
<p class="MsoNormal">In the limited testing I’ve done with this, it has worked well. I personally like having someone look at my code with me and let me know what I could have done better, or what piece of code is not quite as intuitive as I thought it was (everything I write is totally intuitive – to me!). I’m curious as to what other people’s thoughts and experiences with regards to peer reviews are, however.</p>
]]></content:encoded>
			<wfw:commentRSS>http://www.spenceruresk.com/2008/05/26/avoiding-unpleasant-code-with-peer-reviews/feed/</wfw:commentRSS>
		<feedburner:origLink>http://www.spenceruresk.com/2008/05/26/avoiding-unpleasant-code-with-peer-reviews/</feedburner:origLink></item>
		<item>
		<title>Amazon Associates Web Service with GroovyWS</title>
		<link>http://feedproxy.google.com/~r/Spenceruresk/~3/JPuwJjXqPck/</link>
		<comments>http://www.spenceruresk.com/2008/05/18/amazon-associates-web-service-with-groovyws/#comments</comments>
		<pubDate>Mon, 19 May 2008 02:36:06 +0000</pubDate>
		<dc:creator>suresk</dc:creator>
		
	<category>Technology</category>
	<category>Web Services</category>
	<category>Java</category>
	<category>Groovy</category>
		<guid isPermaLink="false">http://www.spenceruresk.com/2008/05/18/amazon-associates-web-service-with-groovyws/</guid>
		<description><![CDATA[I couldn&#8217;t find any tutorials on how to use Amazon AWS with GroovyWS, so I took a few minutes to figure out how to do it. Here is some sample code:


import groovyx.net.ws.WSClient

def proxy = new WSClient&#40;&#8220;http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl?&#8221;, this.class.classLoader&#41;

def req = proxy.create&#40;&#8220;com.amazon.webservices.awsecommerceservice._2008_04_07.ItemSearchRequest&#8221;&#41;

req.searchIndex = &#8216;Books&#8217;
req.keywords = &#8220;Groovy and Grails&#8221;

def search = proxy.create&#40;&#8220;com.amazon.webservices.awsecommerceservice._2008_04_07.ItemSearch&#8221;&#41;

search.AWSAccessKeyId = &#8220;your id here&#8221;
search.request.add&#40;req&#41;

def res = [...]]]></description>
			<content:encoded><![CDATA[<p>I couldn&#8217;t find any tutorials on how to use Amazon AWS with GroovyWS, so I took a few minutes to figure out how to do it. Here is some sample code:</p>
<pre>
<div class="codesnip-container" >
<div class="codesnip"><span class="co2">import groovyx.net.ws.WSClient</span>

def proxy = <span class="kw2">new</span> WSClient<span class="br0">&#40;</span><span class="st0">&#8220;http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl?&#8221;</span>, <span class="kw2">this</span>.<span class="kw2">class</span>.<span class="me1">classLoader</span><span class="br0">&#41;</span>

def req = proxy.<span class="me1">create</span><span class="br0">&#40;</span><span class="st0">&#8220;com.amazon.webservices.awsecommerceservice._2008_04_07.ItemSearchRequest&#8221;</span><span class="br0">&#41;</span>

req.<span class="me1">searchIndex</span> = <span class="st0">&#8216;Books&#8217;</span>
req.<span class="me1">keywords</span> = <span class="st0">&#8220;Groovy and Grails&#8221;</span>

def search = proxy.<span class="me1">create</span><span class="br0">&#40;</span><span class="st0">&#8220;com.amazon.webservices.awsecommerceservice._2008_04_07.ItemSearch&#8221;</span><span class="br0">&#41;</span>

search.<span class="me1">AWSAccessKeyId</span> = <span class="st0">&#8220;your id here&#8221;</span>
search.<span class="me1">request</span>.<span class="me1">add</span><span class="br0">&#40;</span>req<span class="br0">&#41;</span>

def res = proxy.<span class="me1">ItemSearch</span><span class="br0">&#40;</span>search<span class="br0">&#41;</span>

res.<span class="me1">getItems</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">each</span> <span class="br0">&#123;</span>it.<span class="me1">getItem</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">each</span> <span class="br0">&#123;</span>
println it.<span class="me1">getASIN</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#125;</span><span class="br0">&#125;</span></div>
</div>
</pre>
<p>If you&#8217;ve downloaded the <a href="http://groovy.codehaus.org/GroovyWS">GroovyWS</a> jar and put it in your GROOVY_HOME/lib, that should work. I think it is kinda cool how quick and easy it is you can get something simple working with GroovyWS, but if you are going to be using Amazon Web Services a lot, it is probably easier to grab the Java Library that Amazon provides and use it. Here is the code for using that in Groovy:</p>
<pre>
<div class="codesnip-container" >
<div class="codesnip"><span class="co2">import com.amazonaws.a2s.model.*;</span>
<span class="co2">import com.amazonaws.a2s.*;</span>

<span class="kw2">class</span> AmazonSearch <span class="br0">&#123;</span>

<a href="http://www.google.com/search?q=allinurl%3AString+java.sun.com&#038;bntl=1"><span class="kw3">String</span></a> key = <span class="st0">&#8216;your key&#8217;</span>
<a href="http://www.google.com/search?q=allinurl%3AString+java.sun.com&#038;bntl=1"><span class="kw3">String</span></a> tag = <span class="st0">&#8216;your associates tag&#8217;</span>

def doSearch<span class="br0">&#40;</span><a href="http://www.google.com/search?q=allinurl%3AString+java.sun.com&#038;bntl=1"><span class="kw3">String</span></a> keywords<span class="br0">&#41;</span> <span class="br0">&#123;</span>
AmazonA2S service = <span class="kw2">new</span> AmazonA2SClient<span class="br0">&#40;</span>key, tag<span class="br0">&#41;</span>
ItemSearchRequest request = <span class="kw2">new</span> ItemSearchRequest<span class="br0">&#40;</span><span class="br0">&#41;</span>
request.<span class="me1">searchIndex</span> = <span class="st0">&#8216;Books&#8217;</span>
request.<span class="me1">keywords</span> = keywords
processRequest<span class="br0">&#40;</span>service, request<span class="br0">&#41;</span>
<span class="br0">&#125;</span>

<span class="kw2">private</span> processRequest<span class="br0">&#40;</span>AmazonA2S service, ItemSearchRequest request<span class="br0">&#41;</span> <span class="br0">&#123;</span>
ItemSearchResponse response = service.<span class="me1">itemSearch</span><span class="br0">&#40;</span>request<span class="br0">&#41;</span>
response.<span class="me1">getItems</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">getItem</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">each</span> <span class="br0">&#123;</span>
println it.<span class="me1">getASIN</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#125;</span>
<span class="br0">&#125;</span>

<span class="kw4">static</span> <span class="kw4">void</span> main<span class="br0">&#40;</span>args<span class="br0">&#41;</span> <span class="br0">&#123;</span>
AmazonSearch search = <span class="kw2">new</span> AmazonSearch<span class="br0">&#40;</span><span class="br0">&#41;</span>
search.<span class="me1">doSearch</span><span class="br0">&#40;</span><span class="st0">&#8220;Groovy and Grails&#8221;</span><span class="br0">&#41;</span>
<span class="br0">&#125;</span>

<span class="br0">&#125;</span></div>
</div>
</pre>
]]></content:encoded>
			<wfw:commentRSS>http://www.spenceruresk.com/2008/05/18/amazon-associates-web-service-with-groovyws/feed/</wfw:commentRSS>
		<feedburner:origLink>http://www.spenceruresk.com/2008/05/18/amazon-associates-web-service-with-groovyws/</feedburner:origLink></item>
		<item>
		<title>Why aren’t more IT workers telecommuting?</title>
		<link>http://feedproxy.google.com/~r/Spenceruresk/~3/Z8yCj0_5R-U/</link>
		<comments>http://www.spenceruresk.com/2008/04/27/why-arent-more-it-workers-telecommuting/#comments</comments>
		<pubDate>Sun, 27 Apr 2008 21:14:08 +0000</pubDate>
		<dc:creator>suresk</dc:creator>
		
	<category>Economics</category>
	<category>Business</category>
	<category>Software Development</category>
		<guid isPermaLink="false">http://www.spenceruresk.com/2008/04/27/why-arent-more-it-workers-telecommuting/</guid>
		<description><![CDATA[With the skyrocketing cost of fuel and the increasing impact of fuel costs on American workers, I have to ask - Why aren&#8217;t more people telecommuting? My comments are specifically for IT-related jobs, since that is where my experience is, but I believe a fairly large number of other jobs could be done via telecommuting [...]]]></description>
			<content:encoded><![CDATA[<p>With the skyrocketing cost of fuel and the increasing impact of fuel costs on American workers, I have to ask - Why aren&#8217;t more people telecommuting? My comments are specifically for IT-related jobs, since that is where my experience is, but I believe a fairly large number of other jobs could be done via telecommuting as well.</p>
<p>To give you an idea of why I think telecommuting is feasible (and attractive), here is my typical day, which isn&#8217;t too terribly different from that of many other IT workers:<br />
- Get ready for work, throw my laptop into my backpack, and head out the door.</p>
<p>- Drive the 15 or so miles to work. Usually I am lucky in the morning and it only takes 30 min or so to make the drive.</p>
<p>- Unpack and dock my laptop, and get to work.</p>
<p>- Throughout the day, much of my interaction with my co-workers is done via IM and email. People are too spread out (different floors, different buildings, etc) and often too busy for real-time human interaction all the time.</p>
<p>- Work ends, throw my laptop back into my bag, drive the 15 or so miles home (this trip takes me 45 - 60 minutes).</p>
<p>So, each day I drive 30 miles and spend roughly 1.5 hours commuting to and from work. Over a week, that is 150 miles and 7.5 hours - almost a full workday! Thankfully, the new <a href="http://www.rideuta.com/projects/commuterRail/default.aspx">train</a> is starting to run next week, so some of this will be mitigated, but it is still a fair amount of time and money spent commuting. Add to this other problems that are common for many companies - lack of space, parking issues, and other facility issues.<br />
So, why not have employees telecommute a handful of days per week? Think about the benefits:</p>
<p><strong>Employees</strong></p>
<p>- Less time in traffic<br />
- Less spent on gas and maintenance<br />
- Ability to focus on your tasks for a few days (I get far more done on the rare days I work from home)<br />
<strong><br />
Employers</strong></p>
<p>- Happier employees<br />
- Less need for parking space<br />
- Less floor space needed for employees</p>
<p><strong>Society, the economy, and the environment</strong></p>
<p>- Less gas being used<br />
- Less pollution being created<br />
- Roads that are less congested</p>
<p>I understand as well as anyone the need for people to be at work in-person and to have face-to-face time with other employees. I don&#8217;t think this needs to be every day, though. In fact, I think many of us would benefit from less time available for meetings - people scheduling them would have to think hard about whether or not a full-blown meeting was necessary, or whether whatever they are trying to accomplish could be done with a few emails.<br />
If a large percentage of IT workers worked from home just 2 or 3 days per week, the impact could be quite large - think of all the time and energy savings. There is no good technical reason for not encouraging such policies - technology exists to allow this (many companies already have it in place and use it to a small extent), the nature of our jobs is very conducive to working off-site, and several companies (ie, RedHat), already do it to a large extent with great success.</p>
<p>One argument against telecommuting is that it makes it hard to keep people accountable. I&#8217;d argue that it is pretty easy to see who is getting their stuff done and who isn&#8217;t, regardless of where they are working from. If you are paying someone $100k per year to write code for you and don&#8217;t feel like you can trust them enough to let them work out of your sight for a few days, you have far bigger problems. It also kills me when companies have no problem outsourcing projects halfway around the world to people they don&#8217;t know (and can&#8217;t communicate with very well), but balk at letting employees work from home a few days per week.</p>
<p>I don&#8217;t see why more companies aren&#8217;t pushing this, why government at various levels isn&#8217;t pushing it, and why more employees aren&#8217;t clamoring for it. Yeah, it takes a little extra work, requires some trust on the part of the employer, and may cost a bit in initial setup (VPN, security, bigger pipes to handle the traffic, etc), but to me, it seems like it pays of well in the long run.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://www.spenceruresk.com/2008/04/27/why-arent-more-it-workers-telecommuting/feed/</wfw:commentRSS>
		<feedburner:origLink>http://www.spenceruresk.com/2008/04/27/why-arent-more-it-workers-telecommuting/</feedburner:origLink></item>
		<item>
		<title>iBrick - 2.0</title>
		<link>http://feedproxy.google.com/~r/Spenceruresk/~3/snMjGeT1uJA/</link>
		<comments>http://www.spenceruresk.com/2008/04/08/ibrick-20/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 08:46:18 +0000</pubDate>
		<dc:creator>suresk</dc:creator>
		
	<category>Mobile Development</category>
	<category>Apple</category>
	<category>iPhone</category>
		<guid isPermaLink="false">http://www.spenceruresk.com/2008/04/08/ibrick-20/</guid>
		<description><![CDATA[It looks as though developers using the Apple iPhone 2.0 (Beta) OS (via the official development program) have been completely locked out of their phones within the last few hours, based on posts on Apple&#8217;s forums. To make matters worse, you apparently cannot restore the 1.1.4 firmware. Ouch.

]]></description>
			<content:encoded><![CDATA[<p>It looks as though developers using the Apple iPhone 2.0 (Beta) OS (via the official development program) have been completely locked out of their phones within the last few hours, based on posts on <a href="http://discussions.apple.com/thread.jspa?threadID=1476829&#038;tstart=0">Apple&#8217;s forums</a>. To make matters worse, you apparently cannot restore the 1.1.4 firmware. Ouch.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://www.spenceruresk.com/2008/04/08/ibrick-20/feed/</wfw:commentRSS>
		<feedburner:origLink>http://www.spenceruresk.com/2008/04/08/ibrick-20/</feedburner:origLink></item>
		<item>
		<title>No debugging on the iPhone for a while</title>
		<link>http://feedproxy.google.com/~r/Spenceruresk/~3/_zGjsXwLqec/</link>
		<comments>http://www.spenceruresk.com/2008/03/21/no-debugging-on-the-iphone-for-a-while/#comments</comments>
		<pubDate>Sat, 22 Mar 2008 02:44:30 +0000</pubDate>
		<dc:creator>suresk</dc:creator>
		
	<category>Mobile Development</category>
	<category>Apple</category>
	<category>iPhone</category>
	<category>Xcode</category>
		<guid isPermaLink="false">http://www.spenceruresk.com/2008/03/21/no-debugging-on-the-iphone-for-a-while/</guid>
		<description><![CDATA[I was pretty excited when I saw that you can debug your iPhone apps on your actual phone with Apple&#8217;s SDK. Not being one to bother with instructions, I downloaded the new version of Xcode and started hacking away on a sample iPhone app. When I went to try it out, I got this error: [...]]]></description>
			<content:encoded><![CDATA[<p>I was pretty excited when I saw that you can debug your iPhone apps on your actual phone with Apple&#8217;s SDK. Not being one to bother with instructions, I downloaded the new version of Xcode and started hacking away on a sample iPhone app. When I went to try it out, I got this error: &#8220;Codesign error: no certificate for identifier &#8220;iPhone Developer&#8221; was found in your keychain&#8221;.</p>
<p>Reading through the instructions, I found that I needed to be a registered iPhone developer - and pay $99 for the privilege. Not a big deal, but after I signed up (I wasn&#8217;t asked to pay), I was told I would be contacted when I could complete the registration and (presumably) get my certificate.</p>
<p>I don&#8217;t really mind paying $99, but having to wait around for them to let me in is kind of a let-down. Bummer.
</p>
]]></content:encoded>
			<wfw:commentRSS>http://www.spenceruresk.com/2008/03/21/no-debugging-on-the-iphone-for-a-while/feed/</wfw:commentRSS>
		<feedburner:origLink>http://www.spenceruresk.com/2008/03/21/no-debugging-on-the-iphone-for-a-while/</feedburner:origLink></item>
	</channel>
</rss>
