<?xml version="1.0" encoding="UTF-8"?>
<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:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Glen Smith</title>
	
	<link>http://blogs.bytecode.com.au/glen</link>
	<description>Java, XML and all that Jazz... from Canberra, Australia</description>
	<lastBuildDate>Fri, 12 Apr 2013 04:17:23 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/glensmith" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="glensmith" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><image><url>http://blogs.bytecode.com.au/favicon.ico</url></image><item>
		<title>Exploring the Grails Cache Plugin: Evicting Multiple Caches</title>
		<link>http://blogs.bytecode.com.au/glen/2013/04/12/exploring-the-grails-cache-plugin-evicting-multiple-caches.html</link>
		<comments>http://blogs.bytecode.com.au/glen/2013/04/12/exploring-the-grails-cache-plugin-evicting-multiple-caches.html#comments</comments>
		<pubDate>Fri, 12 Apr 2013 04:14:24 +0000</pubDate>
		<dc:creator>Glen</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>

		<guid isPermaLink="false">http://blogs.bytecode.com.au/glen/?p=906</guid>
		<description><![CDATA[The more recent version of Grails bundle a cute little Cache plugin that abstracts some of the Cache classes built into Spring 3.1. For the common use cases, you can simply make use of the @Cacheable annotation, and then make use of @CacheEvict when you need to clean things out. But this sample code demonstrates [...]]]></description>
				<content:encoded><![CDATA[<p>The more recent version of Grails bundle a cute little <a href="http://grails-plugins.github.com/grails-cache/docs/manual/">Cache plugin</a> that abstracts some of the Cache classes built into Spring 3.1. For the common use cases, you can simply make use of the <a href="http://grails-plugins.github.com/grails-cache/docs/manual/guide/usage.html#annotations">@Cacheable</a> annotation, and then make use of <a href="http://grails-plugins.github.com/grails-cache/docs/manual/guide/usage.html#annotations">@CacheEvict</a> when you need to clean things out. But this sample code demonstrates what to do when you need to evict several caches on a  single method call (for instance, because your changing the underlying data that may have been cached in several different calcs).</p>
<p>If you haven&#8217;t played with the Cache plugin before, here&#8217;s the skinny. Imagine you have a controller or service that performs a couple of  expensive operations on some shared dataset (you are going to refactor it into a service, right? <img src='http://blogs.bytecode.com.au/glen/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Here&#8217;s our skeleton placeholder:</p>
<pre class="brush: groovy; gutter: true">package hubbub

import grails.plugin.cache.CacheEvict
import grails.plugin.cache.Cacheable
import java.util.concurrent.atomic.AtomicInteger

class CounterController {

    static defaultAction = &quot;invalidatingMethod&quot;

    static AtomicInteger counter = new AtomicInteger()

    @Cacheable(&quot;myCache&quot;)
    def expensiveMethod1() {

    	// imagine the massive query from hell
    	render &quot;The latest value is ${counter.incrementAndGet()}&quot;

    }

    @Cacheable(&quot;myOtherCache&quot;)
    def expensiveMethod2() {

    	// imagine another massive query from hell
    	render &quot;The latest value is ${counter.incrementAndGet()}&quot;

    }

    @CacheEvict(value=[&#039;myCache&#039;,&#039;myOtherCache&#039;], allEntries=true)
    def invalidatingMethod() {
    	// Something that would invalidate the cache... like a DB update
    	render &quot;The caches have been cleared&quot;
    }
}</pre>
<p>So our expensiveMethod1() and expensiveMethod2() have been marked @Cacheable. This means that Grails will intercept the calls, to these method, catch the return values and squirrel them off to the Cacheing infrastructure (in memory by default, so it will be reset on JVM restart).  Next time you call the method, Grails will returned the cached value (which saves you all that processing time).</p>
<p>In the scenario above, I&#8217;m using two different caches with two different names. I&#8217;m then using the annotation on invalidatingMethod() to clear an array of cache names in one hit! I&#8217;m not sure that&#8217;s covered in the current docs, I had to go hunting through the source. But at least it&#8217;s now google-able!</p>
<p>So, I&#8217;ve made my calls to each of my cached methods and confirmed they are returning cached values, for instance. :</p>
<ol>
<li>http://localhost:8080/hubbub/counter/expensiveMethod1 » The latest value is 1</li>
<li>http://localhost:8080/hubbub/counter/expensiveMethod2 » The latest value is 2</li>
<li>http://localhost:8080/hubbub/counter/expensiveMethod1 » The latest value is 1</li>
<li>http://localhost:8080/hubbub/counter/expensiveMethod2 » The latest value is 2</li>
</ol>
<p>Imaging I then made method calls my invalidating method, and you can see how the cache is operating on the data (or copy and paste and try it at home for even more XP)</p>
<ol>
<li>http://localhost:8080/hubbub/counter/invalidatingMethod » The caches have been cleared</li>
<li>http://localhost:8080/hubbub/counter/expensiveMethod1 » The latest value is 3</li>
<li>http://localhost:8080/hubbub/counter/expensiveMethod2 » The latest value is 4</li>
<li>http://localhost:8080/hubbub/counter/expensiveMethod1 » The latest value is 3</li>
<li>http://localhost:8080/hubbub/counter/expensiveMethod2 » The latest value is 4</li>
</ol>
<p>So the first invocation to the cached method after the caches have been cleared repopulates the cache with the new value. Awesome!</p>
<p>This new lightweight caching is a very cool feature of Grails 2.x line and you should definitely checkout the docs to see way you can configure those caches to be persistent, overflow, etc.</p>
<p>Happy Caching!</p>
<p>(Regular shameless plugin: If you want to find out more about what&#8217;s new in Grails 2.x, make sure you checkout the MEAP of <a href="http://www.manning.com/gsmith2/">Grails in Action 2</a> which is now on the Manning Site and for which we&#8217;ll soon be releasing the plugins chapter which covers Caching and other goodness).</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.bytecode.com.au/glen/2013/04/12/exploring-the-grails-cache-plugin-evicting-multiple-caches.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Extracting the raw XML of an element using Commons Digester</title>
		<link>http://blogs.bytecode.com.au/glen/2013/04/12/extracting-the-raw-xml-of-an-element-using-commons-digester.html</link>
		<comments>http://blogs.bytecode.com.au/glen/2013/04/12/extracting-the-raw-xml-of-an-element-using-commons-digester.html#comments</comments>
		<pubDate>Fri, 12 Apr 2013 04:11:38 +0000</pubDate>
		<dc:creator>Glen</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blogs.bytecode.com.au/glen/?p=929</guid>
		<description><![CDATA[I&#8217;ve recently had to parse out some semi-structured xml and marshall it into an object graph. I&#8217;d normally use JAXB in a heartbeat but the random, schemaless design of this particular large xml doc (full of random reuse of tag names inside other tags as you&#8217;ll see) made that pretty much impossible. So I was [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve recently had to parse out some semi-structured xml and marshall it into an object graph. I&#8217;d normally use JAXB in a heartbeat but the random, schemaless design of this particular large xml doc (full of random reuse of tag names inside other tags as you&#8217;ll see) made that pretty much impossible.</p>
<p>So I was originally thinking of doing it all by hand in <a href="http://docs.oracle.com/javaee/5/tutorial/doc/bnbem.html">StaX</a> using the XmlEventReader. After all, it&#8217;s build into modern Java platforms and gives you the freedom to do what you want. But there&#8217;s the small matter of writing your own state-tracking using Stacks or whatnot.</p>
<p>The other night at  our local <a href="http://www.cjugaustralia.org/">Canberra JUG</a> we were talking about how great <a href="http://commons.apache.org/proper/commons-digester/">Commons Digester </a>was for this stuff back in the day. Well, I figured I revisit it and it turns out Digester3 was just the ticket for my little problem. If you&#8217;re interested in a tutorial, there&#8217;s a <a href="http://ted-gao.blogspot.com.au/2011/09/apache-commons-digester-3-basics.html">great one here</a>.</p>
<p>But one FAQ remained. I needed to slurp out a few of the nested nodes in the xml as an xml string. The docs are pretty lean on such things, but it turns out there&#8217;s plenty of magic in the framework to help you out.</p>
<p>First, you&#8217;ll need to take advantage of the <a href="http://commons.apache.org/proper/commons-digester/commons-digester-3.2/apidocs/org/apache/commons/digester3/NodeCreateRule.html">NoteCreateRule</a> object which invoke your parsed object with an xml Element of the matched node:</p>
<pre class="brush: java; gutter: true"> forPattern(&quot;manual/part/chapter/section/controlsTitle/block/controls/block/content&quot;).
    addRule(new NodeCreateRule()).then().setNext(&quot;setDescriptionFromXml&quot;);</pre>
<p>Once you have a handle to that bad boy, it&#8217;s just a matter of adding a method to your target bean object that takes such a beast. A little help from <a href="http://stackoverflow.com/questions/1219596/how-to-i-output-org-w3c-dom-element-to-string-format-in-java">Stack Overflow</a>, and I can turn that xml into a String and strip out the tags for my own nefarious reasons&#8230;</p>
<pre class="brush: java; gutter: true">  // http://stackoverflow.com/questions/1219596/how-to-i-output-org-w3c-dom-element-to-string-format-in-java
    public void setDescriptionFromXml(Element element) throws Exception {
        TransformerFactory transFactory = TransformerFactory.newInstance();
        Transformer transformer = transFactory.newTransformer();
        StringWriter buffer = new StringWriter();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, &quot;yes&quot;);
        transformer.transform(new DOMSource(element), new StreamResult(buffer));
        String str = buffer.toString().replaceAll(&quot;\\&lt;.*?\\&gt;&quot;, &quot;&quot;).trim(); // strip all XML tags
        setDescription(str);

    }</pre>
<p>Anyways, I thought it was worth writing up the process in case you ever need to use Commons Digester to get at the raw xml of a portion of your parse tree.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.bytecode.com.au/glen/2013/04/12/extracting-the-raw-xml-of-an-element-using-commons-digester.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Lesser Known Grails Tag: g:external</title>
		<link>http://blogs.bytecode.com.au/glen/2013/01/30/a-lesser-known-grails-tag-gexternal.html</link>
		<comments>http://blogs.bytecode.com.au/glen/2013/01/30/a-lesser-known-grails-tag-gexternal.html#comments</comments>
		<pubDate>Wed, 30 Jan 2013 06:20:21 +0000</pubDate>
		<dc:creator>Glen</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>

		<guid isPermaLink="false">http://blogs.bytecode.com.au/glen/?p=893</guid>
		<description><![CDATA[Working on refreshing the &#8220;tasty views and layouts&#8221; chapter for Grails in Action 2.0 and came across the gem that is the g:external tag. Grails 2.0 introduced this cute little tag called &#60;g:external&#62; for that very common case of linking to CSS, JavaScript and favicons. Back in the old days, you used to use some [...]]]></description>
				<content:encoded><![CDATA[<p>Working on refreshing the &#8220;tasty views and layouts&#8221; chapter for <a href="http://www.manning.com/gsmith2/">Grails in Action 2.0</a> and came across the gem that is the <a href="http://grails.org/doc/latest/ref/Tags/external.html">g:external </a>tag.</p>
<p>Grails 2.0 introduced this cute little tag called <a href="http://grails.org/doc/latest/ref/Tags/external.html">&lt;g:external&gt;</a> for that very common case of linking to CSS, JavaScript and favicons. Back in the old days, you used to use some kind of &#8220;resource&#8221; link, perhaps as a method call for brevity (or in the even older days you might have used a createLinkTo tag, but that&#8217;s showing my age):</p>
<pre class="brush: html; gutter: true">&lt;link rel=&quot;stylesheet&quot; href=&quot;${resource(dir:&#039;css&#039;,file:&#039;hubbub.css&#039;)}&quot; /&gt;</pre>
<p>But these days, &lt;g:external&gt; is the tag for you! It will sense whether you&#8217;re linking to css, javascript, some kind of image (for a favicon), or that crazy Apple-icon-specific-thing, and generate the appropriate &lt;link&gt; tag for you. Behold the magic of external:</p>
<pre class="brush: html; gutter: true">&lt;g:external dir=&#039;css&#039; file=&#039;hubbub.css&#039;/&gt;</pre>
<p>This will generate the full &lt;link&gt; text you need, including the appropriate context for your app:</p>
<pre class="brush: html; gutter: true">&lt;link href=&quot;/hubbub/static/css/hubbub.css&quot; type=&quot;text/css&quot; rel=&quot;stylesheet&quot; 
       media=&quot;screen, projector&quot; dir=&quot;css&quot; file=&quot;hubbub.css&quot; 
       contextPath=&quot;/hubbub&quot;/&gt;</pre>
<p>But the truly wonderful part of the little gem of a tag (as you&#8217;ll notice in the generated code above) is that it is<a href="http://grails-plugins.github.com/grails-resources/guide/"> resources-aware</a>. That means that you get cache-able goodness of the resources plugin, along with all the static-mapping magic that exposes to you.</p>
<p>There is also a uri version of the tag has a little less ceremony where you link context relevant content and it will be scooped up and re-written, however it didn&#8217;t seem to happen for me on 2.2.0&#8230;</p>
<pre class="brush: html; gutter: true">&lt;g:external uri=&#039;/css/hubbub.css&#039;/&gt;</pre>
<p>No time to waste! Go forth and externalise! Just perfect for your next CSS, JS and Favicon &lt;link&gt; usage!</p>
<p>(Oh, PS. if you&#8217;re after a Grails 2.0 book to get started, shameless plugin for<a href="http://www.manning.com/gsmith2/"> Grails in Action 2.0 which is in MEAP</a>.)</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.bytecode.com.au/glen/2013/01/30/a-lesser-known-grails-tag-gexternal.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Has my File finished copying to my uploads directory?</title>
		<link>http://blogs.bytecode.com.au/glen/2013/01/23/has-my-file-finished-copying-to-my-uploads-directory.html</link>
		<comments>http://blogs.bytecode.com.au/glen/2013/01/23/has-my-file-finished-copying-to-my-uploads-directory.html#comments</comments>
		<pubDate>Wed, 23 Jan 2013 09:16:29 +0000</pubDate>
		<dc:creator>Glen</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blogs.bytecode.com.au/glen/?p=887</guid>
		<description><![CDATA[So your Java app is scanning an uploads directory for files that the user will copy in (perhaps via a Windows share). The only snag is that the files can be very large, and you don&#8217;t want to *start* processing a partially uploaded file. What to do? So, today&#8217;s challenge: finding a way to tell [...]]]></description>
				<content:encoded><![CDATA[<p>So your Java app is scanning an uploads directory for files that the user will copy in (perhaps via a Windows share). The only snag is that the files can be very large, and you don&#8217;t want to *start* processing a partially uploaded file. What to do?</p>
<p>So, today&#8217;s challenge: finding a way to tell if a given File has completed copying to the upload directory or is still in the process of being copied. A colleague pointed me at <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/package-summary.html">nio</a>, and we threw together something to get the job done (we already knew that File.exists() and File.canRead(), so your effort may need to be a little more robust than this one, but this will get you started):</p>
<pre class="brush: java; gutter: true">   private boolean hasFinishedCopying(File file) {
     
        FileInputStream fis = null;
        FileLock lock = null;
        try {
            fis = new FileInputStream(file);
            FileChannel fc = fis.getChannel();
            lock = fc.tryLock(0L, Long.MAX_VALUE, true);
        } catch (IOException ioe) {
            return false;
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException ioe) {
                    // give up...
                }
            }
        }
        return lock != null;
    }</pre>
<p>The magic you need to be aware of is that third boolean argument to tryLock() on a <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/channels/FileChannel.html">FileChannel</a>. That says &#8220;I want to try to get a shared lock on this file for reading and I under someone else might be writing at the moment&#8221;. That&#8217;s just my scenario! (And without that shared switch you&#8217;ll end up with a <a href="http://docs.oracle.com/javase/6/docs/api/java/nio/channels/NonWritableChannelException.html">NonWritableChannelException</a>).</p>
<p>There&#8217;s probably a better way of accomplishing this task, but I thought I would at least blog up one option that we&#8217;ve tested to work, so that I can Google this later (since I am sure this is a problem I faced before!).</p>
<p>Happy locking!</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.bytecode.com.au/glen/2013/01/23/has-my-file-finished-copying-to-my-uploads-directory.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Getting TomEE working with JBoss Developer Tools 6</title>
		<link>http://blogs.bytecode.com.au/glen/2013/01/04/getting-tomee-working-with-jboss-developer-tools-6.html</link>
		<comments>http://blogs.bytecode.com.au/glen/2013/01/04/getting-tomee-working-with-jboss-developer-tools-6.html#comments</comments>
		<pubDate>Fri, 04 Jan 2013 09:10:14 +0000</pubDate>
		<dc:creator>Glen</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blogs.bytecode.com.au/glen/?p=874</guid>
		<description><![CDATA[I&#8217;ve spent the day playing around with TomEE 1.5 plus and I have to say that I&#8217;m very impressed. The server starts up in a heartbeat, I could happily deploy my Glassfish EE6/PrimeFaces/JPA2 maven war to it with no app config changes to the app (bar a resource-ref). That&#8217;s pretty impressive since it&#8217;s using a [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve spent the day playing around with <a href="http://tomee.apache.org/">TomEE 1.5 plus</a> and I have to say that I&#8217;m very impressed. The server starts up in a heartbeat, I could happily deploy my Glassfish EE6/<a href="http://www.primefaces.org/">PrimeFaces</a>/JPA2 maven war to it with no app config changes to the app (bar a resource-ref). That&#8217;s pretty impressive since it&#8217;s using a completely different JPA provider, EJB container, and JSF implementation! Go the TCK!</p>
<p>Just for putting the cream on top, the brief smoke test I did will <a href="http://jmeter.apache.org/">JMeter</a> showed that it is likely to perform with ample headroom under my anticipated load.</p>
<p>The one snag I did have was getting it integrated into <a href="http://devstudio.jboss.com/">JBoss Developer Studio </a>(basically a customised Eclipse). Even though there are <a href="http://tomee.apache.org/tomee-and-eclipse.html">great instructions</a> on the TomEE site, I was a bit lost as to exactly which windows that the text was describing.</p>
<p>So here&#8217;s the skinny..</p>
<p>Open up the Server window and add a new Tomcat 7 server, giving it the path to your Tom EE installation. Follow the wizard and live the default lifestyle.</p>
<p>After that you&#8217;ll get a Servers twisty that appears under project in the Project Explorer window (normally the big window on the far left in the default implementation). When you fold out that server, you&#8217;ll see that it&#8217;s only got the tomcat config files (no tomee.xml or any of the other tomee specific configs). Without those you&#8217;ll get weird errors about mapping your JPA providers to HSQLDB or My Data Source or some other bizarre default.</p>
<p><a href="http://blogs.bytecode.com.au/glen/2013/01/04/getting-tomee-working-with-jboss-developer-tools-6.html/dev-studio-project" rel="attachment wp-att-878"><img class="alignnone size-full wp-image-878" alt="dev-studio-project" src="http://blogs.bytecode.com.au/glen/wp-content/uploads/2013/01/dev-studio-project.png" width="251" height="219" /></a></p>
<p>&nbsp;</p>
<p>So what you&#8217;ll need to do is right click on the &#8220;Tomcat v7.0 Server&#8221; entry above, and select /Import&#8230;/General/File System/ and select the logging.properties, system.properites and tomee.xml entries. With those inplace, your JBoss Develop Studio can happily spark up TomEE right inside the IDE.</p>
<p><a href="http://blogs.bytecode.com.au/glen/2013/01/04/getting-tomee-working-with-jboss-developer-tools-6.html/eclipse-adding-files-window" rel="attachment wp-att-875"><img class="alignnone size-medium wp-image-875" alt="eclipse-adding-files-window" src="http://blogs.bytecode.com.au/glen/wp-content/uploads/2013/01/eclipse-adding-files-window-300x298.png" width="300" height="298" /></a></p>
<p>&nbsp;</p>
<p>Once you&#8217;ve got all that infrastructure in place, click on your Servers tab (not in the Project Explorer view, but in the actual Servers view ala /Window/Show View/Servers) . You&#8217;ll now be able to right click on your Tomcat Server and click Start&#8230;</p>
<p><a href="http://blogs.bytecode.com.au/glen/2013/01/04/getting-tomee-working-with-jboss-developer-tools-6.html/servers-tab" rel="attachment wp-att-879"><img class="alignnone size-full wp-image-879" alt="servers-tab" src="http://blogs.bytecode.com.au/glen/wp-content/uploads/2013/01/servers-tab.png" width="475" height="115" /></a></p>
<p>&nbsp;</p>
<p>Enjoy your rapid turnaround cycles!</p>
<p>The only snag I&#8217;ve hit so far is that I haven&#8217;t been able to get in working with SQL Server <a href="http://jtds.sourceforge.net/">jTDS</a> data sources using Integrated Security. It&#8217;s fine when I specify a username/password, but not happy if I leave those blank. But that&#8217;s for another day&#8230;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.bytecode.com.au/glen/2013/01/04/getting-tomee-working-with-jboss-developer-tools-6.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reviewing my Personal Tech Goals for 2012</title>
		<link>http://blogs.bytecode.com.au/glen/2013/01/01/reviewing-my-personal-tech-goals-for-2012.html</link>
		<comments>http://blogs.bytecode.com.au/glen/2013/01/01/reviewing-my-personal-tech-goals-for-2012.html#comments</comments>
		<pubDate>Mon, 31 Dec 2012 23:57:09 +0000</pubDate>
		<dc:creator>Glen</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blogs.bytecode.com.au/glen/?p=860</guid>
		<description><![CDATA[Well, I started 2012 with list of tech goals for 2012, and since it&#8217;s Jan 1st, it&#8217;s probably time for a small retrospective to see how I went. Grails 2.0 Deep Dive. Did ok on this one. I&#8217;ve spend most of the year working full time on a big commercial Grails application, and this year [...]]]></description>
				<content:encoded><![CDATA[<p>Well, I started 2012 with <a title="Some Personal Tech Goals for 2012" href="http://blogs.bytecode.com.au/glen/2012/01/20/some-personal-tech-goals-for-2012.html">list of tech goals</a> for 2012, and since it&#8217;s Jan 1st, it&#8217;s probably time for a small retrospective to see how I went.</p>
<ul>
<li><strong>Grails 2.0 Deep Dive</strong>. Did ok on this one. I&#8217;ve spend most of the year working full time on a big commercial Grails application, and this year I definitely levelled up my commercial development. In particular, I&#8217;ve done a lot of work with evolving schemas in a deployed commercial product using the <a href="http://grails.org/plugin/database-migration">db migrations</a> plugin, written a truckload of <a href="http://grails.org/plugin/spock">Spock</a> tests, and applied some tricky corner cases in <a href="http://grails.org/plugin/spring-security-core">Spring Security</a> Active Directory integration. Also did lots with the new <a href="http://grails.org/plugin/resources">Resources</a> plugin, and had plenty of fun with <a href="http://grails.org/plugin/elasticsearch">Elastic Search</a>.  Somewhere in there I wrote the first half of <a href="http://www.manning.com/gsmith2/">Grails in Action 2nd Ed</a>, and am looking forward to knocking off my remaining chapters early this year. In terms of going deeper, have really enjoyed reading Burt&#8217;s <a href="http://shop.oreilly.com/product/0636920024750.do">hardcore book</a>, and <a href="http://www.apress.com/java/java-ee/9781430243779">Jeff and Graeme&#8217;s new book</a> should be out soon too..</li>
<li><strong>GUI Applications</strong>. I had a couple of Swing client projects slated for this year, but only one of them happened. Turns out Swing was just as complex as I remembered it <img src='http://blogs.bytecode.com.au/glen/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . To be fair, if Java SE had the Events stuff from CDI built in, I think I&#8217;d find things a lot more attractive.</li>
<li><strong>Integration Testing.</strong> Did some tinkering with <a href="http://www.gebish.org/">Geb</a> this year, but didn&#8217;t really make it to the place where I wanted to get to. Need to circle back on this one this year.</li>
<li><strong>JBoss</strong>. Yes indeed. Really connected with our local Aussie JBoss folk this year, and they are an awesome bunch. Really strong hacker culture in that org, right down to the grass roots. Going to be doing a lot more with them in 2013 and really looking forward to connecting up with a few more of the players in that space. And to play with <a href="http://arquillian.org/">Arquillian</a> in anger.</li>
<li><strong>MongoDb</strong>. Didn&#8217;t happen this year. I&#8217;m really excited about the schemaless model of Mongo, just didn&#8217;t come across a project this year that would have had significant benefit from it. Might be time to cook up a hobby project in 2013, just to get dirtier hands.</li>
</ul>
<p>So, overall, I learned a ton this year, but didn&#8217;t really end up targeting the area I thought I would. All part of the journey, eh?</p>
<p>In the next post, I&#8217;ll outline what&#8217;s on my learning list for 2013. But I&#8217;m still stewing on what I&#8217;m going to commit to&#8230; but I think the theme will all be around &#8220;lean&#8221; and stripping things right back to basics.</p>
<p>Hope you all have an Amazing 2013 filling the world with awesome software!</p>
<p>Glen.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.bytecode.com.au/glen/2013/01/01/reviewing-my-personal-tech-goals-for-2012.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Apache Shiro with JSF</title>
		<link>http://blogs.bytecode.com.au/glen/2012/12/29/using-apache-shiro-with-jsf.html</link>
		<comments>http://blogs.bytecode.com.au/glen/2012/12/29/using-apache-shiro-with-jsf.html#comments</comments>
		<pubDate>Fri, 28 Dec 2012 19:27:43 +0000</pubDate>
		<dc:creator>Glen</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blogs.bytecode.com.au/glen/?p=851</guid>
		<description><![CDATA[&#160; Update: BalusC has done an amazing post about Shiro/JSF. Head over there instead! I know very little about JSF2, and even less about Apache Shiro, but both have been on the learning list for a while, so this blog will document up how to get them working together from beginner&#8217;s eyes. Be gentle. I&#8217;ve [...]]]></description>
				<content:encoded><![CDATA[<p>&nbsp;</p>
<p><strong>Update</strong>: BalusC has done <a href="http://balusc.blogspot.sg/2013/01/apache-shiro-is-it-ready-for-java-ee-6.html">an amazing post</a> about Shiro/JSF. Head over there instead!</p>
<p>I know very little about JSF2, and even less about <a href="http://shiro.apache.org/">Apache Shiro</a>, but both have been on the learning list for a while, so this blog will document up how to get them working together from beginner&#8217;s eyes. Be gentle. I&#8217;ve deployed the sample to JBoss OpenShift while I&#8217;m experimenting, if you&#8217;d like to <a href="http://shirojsf-bytecode.rhcloud.com/">take it for a spin</a>.</p>
<p>First, you&#8217;ll need a basic shiro.ini file which you can dump in your standard /WEB-INF directory. Here&#8217;s a scratcher to get you started which will protect our &#8220;protected.xhtml&#8221; file and redirect the user to the &#8220;login.xhtml&#8221; file.</p>
<pre class="brush: text; gutter: true">[main]
authc.loginUrl = /login.xhtml
authc = org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter
securityManager.rememberMeManager.cookie.name = demoRememberMe

[users]
admin = secret

[roles]
admin = *

[urls]
/index.xhtml = anon
/protected.xhtml = authc</pre>
<p>&nbsp;</p>
<p>Couple of bits of magic about. The most important one is that you need to be using the PassThruAuthenticatorFilter when you&#8217;re working with JSF (which I found out about <a href="http://shiro-user.582556.n2.nabble.com/JSF-Login-Form-Questions-td7112151.html">here</a>). JSF will do magic stuff with your html INPUT element names, so you won&#8217;t be able to use the standard Shiro form filters that know about username, password, rememberMe form elements. I&#8217;ve also customised the &#8220;rememberMe&#8221; cookie name in the above, just because I was keen to explore how you do that!</p>
<p>With our config in place, next stop is to make the changes in web.xml to ensure that the Shiro filter fires. This is all standard Shiro stuff, no special JSF interplace required:</p>
<pre class="brush: xml; gutter: true">&lt;filter&gt;
        &lt;filter-name&gt;ShiroFilter&lt;/filter-name&gt;
        &lt;filter-class&gt;org.apache.shiro.web.servlet.ShiroFilter&lt;/filter-class&gt;
    &lt;/filter&gt;
    &lt;filter-mapping&gt;
        &lt;filter-name&gt;ShiroFilter&lt;/filter-name&gt;
        &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
        &lt;dispatcher&gt;REQUEST&lt;/dispatcher&gt;
        &lt;dispatcher&gt;FORWARD&lt;/dispatcher&gt;
        &lt;dispatcher&gt;INCLUDE&lt;/dispatcher&gt;
        &lt;dispatcher&gt;ERROR&lt;/dispatcher&gt;
    &lt;/filter-mapping&gt;
    &lt;listener&gt;
        &lt;listener-class&gt;org.apache.shiro.web.env.EnvironmentLoaderListener&lt;/listener-class&gt;
    &lt;/listener&gt;</pre>
<p>&nbsp;</p>
<p>With all our web.xml filters in place, the next step is to write up the basic JSF login form. Here&#8217;s my minimalist version of login.xhtml:</p>
<pre class="brush: html; gutter: true">&lt;?xml version=&#039;1.0&#039; encoding=&#039;UTF-8&#039; ?&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;
	xmlns:h=&quot;http://java.sun.com/jsf/html&quot;
	xmlns:f=&quot;http://java.sun.com/jsf/core&quot;&gt;
&lt;h:head&gt;
	&lt;title&gt;Login Page&lt;/title&gt;
&lt;/h:head&gt;
&lt;h:body&gt;

	&lt;h:form&gt;
		&lt;h:messages /&gt;

		&lt;h2&gt;Login Page&lt;/h2&gt;
		&lt;p&gt;You can use &quot;admin&quot; and &quot;secret&quot; to login.&lt;/p&gt;
		&lt;h:panelGrid columns=&quot;3&quot;&gt;

			&lt;h:outputLabel for=&quot;username&quot; value=&quot;User Name:&quot; /&gt;
			&lt;h:inputText id=&quot;username&quot; value=&quot;#{loginController.username}&quot;
				required=&quot;true&quot; label=&quot;Username&quot; /&gt;
			&lt;h:message for=&quot;username&quot; /&gt;

			&lt;h:outputLabel for=&quot;password&quot; value=&quot;Password:&quot; /&gt;
			&lt;h:inputSecret id=&quot;password&quot; value=&quot;#{loginController.password}&quot;
				label=&quot;Password&quot; /&gt;
			&lt;h:message for=&quot;password&quot; /&gt;

			&lt;h:outputLabel for=&quot;rememberMe&quot; value=&quot;Remember Me:&quot; /&gt;
			&lt;h:selectBooleanCheckbox id=&quot;rememberMe&quot;
				value=&quot;#{loginController.rememberMe}&quot; /&gt;

			&lt;h:commandButton action=&quot;#{loginController.authenticate()}&quot;
				value=&quot;Login&quot; /&gt;

		&lt;/h:panelGrid&gt;
	&lt;/h:form&gt;
&lt;/h:body&gt;
&lt;/html&gt;</pre>
<p>Nothing too special there. We have fields for our username, password and rememberMe, just need to wire it up to our loginController, and life will be good. Here&#8217;s what it looks like so far:</p>
<p><a href="http://blogs.bytecode.com.au/glen/2012/12/29/using-apache-shiro-with-jsf.html/login-page-shiro" rel="attachment wp-att-853"><img class="alignnone size-medium wp-image-853" alt="login-page-shiro" src="http://blogs.bytecode.com.au/glen/wp-content/uploads/2012/12/login-page-shiro-300x181.png" width="300" height="181" /></a></p>
<p>Next, we&#8217;ll need to whip up our loginController JSF backing bean with elements for our username, password, rememberMe, and, of course, logic to do the actual authentication. Here&#8217;s my rough one to get you started:</p>
<pre class="brush: java; gutter: true">package au.com.bytecode.controller;

import java.util.logging.Logger;
import javax.enterprise.inject.Model;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;

/**
 * Simple JSF Controller demonstrating Shiro login/logout process.
 * 
 * @author Glen Smith
 */
@Model
public class LoginController {

	String username;
	String password;
	boolean rememberMe = false;

	private static final Logger log = Logger.getLogger(LoginController.class
			.getName());

	public String authenticate() {

		// Example using most common scenario of username/password pair:
		UsernamePasswordToken token = new UsernamePasswordToken(username,
				password);

		// &quot;Remember Me&quot; built-in:
		token.setRememberMe(rememberMe);

		Subject currentUser = SecurityUtils.getSubject();

		log.info(&quot;Submitting login with username of &quot; + username
				+ &quot; and password of &quot; + password);

		try {
			currentUser.login(token);
		} catch (AuthenticationException e) {
			// Could catch a subclass of AuthenticationException if you like
			log.warning(e.getMessage());
			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(&quot;Login Failed: &quot; + e.getMessage(), e
							.toString()));
			return &quot;/login&quot;;
		}
		return &quot;protected?faces-redirect=true&quot;;

	}

	public String logout() {

		Subject currentUser = SecurityUtils.getSubject();
		try {
			currentUser.logout();
		} catch (Exception e) {
			log.warning(e.toString());
		}
		return &quot;index&quot;;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public boolean getRememberMe() {
		return rememberMe;
	}

	public void setRememberMe(boolean rememberMe) {
		this.rememberMe = rememberMe;
	}

}</pre>
<p>&nbsp;</p>
<p>You probably don&#8217;t want to really log usernames and passwords to the console <img src='http://blogs.bytecode.com.au/glen/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> , but it&#8217;s helpful when you&#8217;re learning how things are hanging together.  The core part of the deal is the authenticate() method. In here, you&#8217;re doing a Shiro authenticate using the standard API hooks.</p>
<p>I&#8217;ve also put together a logout() method above too.  Helpful when testing your cookies out <img src='http://blogs.bytecode.com.au/glen/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . I call this from the protected.xhtml page via a commandButton to force the logout:</p>
<pre class="brush: html; gutter: true">&lt;?xml version=&#039;1.0&#039; encoding=&#039;UTF-8&#039; ?&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;
      xmlns:h=&quot;http://java.sun.com/jsf/html&quot;&gt;
    &lt;h:head&gt;
        &lt;title&gt;Secret Page&lt;/title&gt;
    &lt;/h:head&gt;
    &lt;h:body&gt;
        This is a super secret page.
        &lt;h:form&gt;
            &lt;h:commandButton action=&quot;${loginController.logout()}&quot; value=&quot;Logout&quot;/&gt;
        &lt;/h:form&gt;
    &lt;/h:body&gt;
&lt;/html&gt;</pre>
<p>So there you have it! Shiro integration with JSF turns out to be pretty straightfoward once you&#8217;re aware of that PassThruAuthenticator trick! Next on my explore list is to get Shiro DB realm integration happening with JPA2! Should be some interesting CDI challenges there&#8230;</p>
<p>Once again, if you&#8217;d like to <a href="http://shirojsf-bytecode.rhcloud.com/">take it for a spin</a>, I&#8217;ve deployed it to the JBoss cloud to see what that experience was like (very straightforward so far, topic for another post). Also good to know that Shiro runs fine on cloud services!</p>
<p><strong>Edit:</strong> Even better if you use WebUtils to remember the page that was being intercepted when the user was sent to login as discussed <a href="http://mail-archives.apache.org/mod_mbox/shiro-user/201204.mbox/%3CCAETPiXbFDzOZnj4qOaRXgMv57NisN1xk9wfCGaO+vPM5hR5j3A@mail.gmail.com%3E">here</a>.</p>
<p>Something like this would do the trick&#8230;.</p>
<pre class="brush: java; gutter: true">log.info(&quot;Submitting login with username of &quot; + username
		+ &quot; and password of &quot; + password);

try {
	currentUser.login(token);
	FacesContext fc = FacesContext.getCurrentInstance();
	fc.responseComplete();
	HttpServletRequest request = (HttpServletRequest) fc.getExternalContext().getRequest();
	HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();
	String fallbackUrl = &quot;/index.xhtml&quot;;
	WebUtils.redirectToSavedRequest(request, response, fallbackUrl);
	return null;
} catch (Exception e) {
	// Could catch a subclass of AuthenticationException if you like
	log.warning(e.getMessage());
	FacesContext.getCurrentInstance().addMessage(
			null,
			new FacesMessage(&quot;Login Failed: &quot; + e.getMessage(), e
					.toString()));
	return &quot;/login&quot;;
}</pre>
<pre class="brush: java; gutter: true"></pre>
<p>Happy JSF/Shiro-ing!</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.bytecode.com.au/glen/2012/12/29/using-apache-shiro-with-jsf.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Tuning Android Battery Life with BetterBatteryStats</title>
		<link>http://blogs.bytecode.com.au/glen/2012/12/24/tuning-android-battery-life-with-stats.html</link>
		<comments>http://blogs.bytecode.com.au/glen/2012/12/24/tuning-android-battery-life-with-stats.html#comments</comments>
		<pubDate>Sun, 23 Dec 2012 22:45:24 +0000</pubDate>
		<dc:creator>Glen</dc:creator>
				<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://blogs.bytecode.com.au/glen/?p=840</guid>
		<description><![CDATA[Using Better Battery Stats, I&#8217;ve managed to nearly double my battery life to 3 days, and I&#8221;m pretty darn happy! Indulge my bragging for a bit, and you might get a few ideas that might work for you too! These days I&#8217;m using a Galaxy Nexus mobile phone which I have flashed to the latest [...]]]></description>
				<content:encoded><![CDATA[<p>Using Better Battery Stats, I&#8217;ve managed to nearly double my battery life to 3 days, and I&#8221;m pretty darn happy! Indulge my bragging for a bit, and you might get a few ideas that might work for you too!</p>
<p>These days I&#8217;m using a Galaxy Nexus mobile phone which I have flashed to the latest <a href="https://developers.google.com/android/nexus/images">Factory Image</a> (worth doing if you&#8217;re still stuck on 4.0.x &#8211; totally safe these days and completely legit). The phone is great, but I&#8217;ve been stuck with a day and a half of battery life, which just isn&#8217;t enough for my liking.</p>
<p>If I have a look at the built in battery stats, I&#8217;m seeing something like:</p>
<p><a href="http://blogs.bytecode.com.au/glen/2012/12/24/tuning-android-battery-life-with-stats.html/2012-11-29-13-17-05" rel="attachment wp-att-841"><img class="alignnone size-medium wp-image-841" alt="Battery Life before Tuning" src="http://blogs.bytecode.com.au/glen/wp-content/uploads/2012/12/2012-11-29-13.17.05-168x300.png" width="168" height="300" /></a></p>
<p>&nbsp;</p>
<p>Well, a day and a half is pretty cool. But what exactly is &#8220;Google Services&#8221; and why is it taking so much of my battery? So I set out on a journey to find exactly where all that battery was going. After a bit of googling, a lot of people were recommending blowing $3 on <a href="https://play.google.com/store/apps/details?id=com.asksven.betterbatterystats&amp;hl=en">Better Battery Stats</a> to see exactly where all that battery was going.</p>
<p>Better Battery Stats will tell let you in on Partial Wakelocks (apps that are stopping your phone going into deep sleep and saving tons of battery). Best of all, it operates passively off standard phone events, so gathering stats costs you no battery life at all. It will only start gathering after your first charge, but since that was happening every day, it was no problem <img src='http://blogs.bytecode.com.au/glen/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>So, first look at where things are going:</p>
<p><a href="http://blogs.bytecode.com.au/glen/2012/12/24/tuning-android-battery-life-with-stats.html/firstlookatwakestats" rel="attachment wp-att-842"><img class="alignnone size-medium wp-image-842" alt="FirstLookAtWakeStats" src="http://blogs.bytecode.com.au/glen/wp-content/uploads/2012/12/FirstLookAtWakeStats-168x300.png" width="168" height="300" /></a></p>
<p>&nbsp;</p>
<p>Ok, so first off my wakelocks are being interruped by the phone app itself. Well, 40 mins of talk time isn&#8217;t much for a day or so, but there&#8217;s not much I can do about that!  The two audio settings are related to Music/Podcasting on the way to work (I love <a href="https://play.google.com/store/apps/details?id=com.podkicker">Podkicker Pro</a> so much &#8211; go spend another $3 on that while you&#8217;re in the store).</p>
<p>But look at the &#8220;Count&#8221; setting on that NetworkLocationLocator instances! My phone was waking up thousands of times to just let Google know my current location. The first one of those looks &#8220;maps related&#8221;, and it seems I had Maps running and set to &#8220;always update my location&#8221; even when I wasn&#8217;t using Maps, so that was the first to go.</p>
<p>The second one seems to be related to Google Now (which is also a constant and massive location updater, so that was next on the list). I don&#8217;t actually use it, so I just turned it off!</p>
<p>Ok, another day passes, and I&#8217;ve got a few more hours, but not the massive win I was after. Next round of tuning.</p>
<p><a href="http://blogs.bytecode.com.au/glen/2012/12/24/tuning-android-battery-life-with-stats.html/googletalkmadness" rel="attachment wp-att-843"><img class="alignnone size-medium wp-image-843" alt="GoogleTalkMadness" src="http://blogs.bytecode.com.au/glen/wp-content/uploads/2012/12/GoogleTalkMadness-168x300.png" width="168" height="300" /></a></p>
<p>GTALK_ASYNC_CONN is my next &#8220;Google Services&#8221; worth having a look at. Looks like Google just can&#8217;t handle the fact that something isn&#8217;t letting them know where I am all the time! So next I just disabled Google Talk (since I don&#8217;t use it anyway). Probably just logging out would be enough, but I was in aggressive tuning mode, so I figured I&#8217;d go for the gold.</p>
<p>Bingo! Now I was cooking. Hit the 3 day mark no problems with a similar pattern of phone use:</p>
<p><a href="http://blogs.bytecode.com.au/glen/2012/12/24/tuning-android-battery-life-with-stats.html/thethreedaymilestone" rel="attachment wp-att-844"><img class="alignnone size-medium wp-image-844" alt="TheThreeDayMilestone" src="http://blogs.bytecode.com.au/glen/wp-content/uploads/2012/12/TheThreeDayMilestone-168x300.png" width="168" height="300" /></a></p>
<p>At this point, my biggest wakelock action was just standard Gmail sync and other actual phone services! Woot! For completeness, this was a picture of my current wakelocks:</p>
<p><a href="http://blogs.bytecode.com.au/glen/2012/12/24/tuning-android-battery-life-with-stats.html/3daypartialwakelocks" rel="attachment wp-att-845"><img class="alignnone size-medium wp-image-845" alt="3DayPartialWakelocks" src="http://blogs.bytecode.com.au/glen/wp-content/uploads/2012/12/3DayPartialWakelocks-168x300.png" width="168" height="300" /></a><a href="http://blogs.bytecode.com.au/glen/?p=840&amp;preview=true">Preview</a></p>
<p>Biggest burn is from actual phone calls, listening to Podcasts and download mail! All things that are core to my life that I&#8217;m happy to live with. After that I started looking into Kernel wakelocks (wifi, nfc,etc), and realised that leaving Wifi on all the time was better than turning it off overnight (since 3G was probably more expensive to run).</p>
<p>Anyways, I have my 3 days using the services I like, so I&#8217;m pretty excited.</p>
<p>Go forth and tune!</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.bytecode.com.au/glen/2012/12/24/tuning-android-battery-life-with-stats.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Reflections On Running a Git Course…</title>
		<link>http://blogs.bytecode.com.au/glen/2012/11/13/reflections-on-running-a-git-course.html</link>
		<comments>http://blogs.bytecode.com.au/glen/2012/11/13/reflections-on-running-a-git-course.html#comments</comments>
		<pubDate>Mon, 12 Nov 2012 23:15:52 +0000</pubDate>
		<dc:creator>Glen</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blogs.bytecode.com.au/glen/?p=828</guid>
		<description><![CDATA[Last week I sat down with a dozen people to run them through a basic Git Training Course. I would have said I was &#8220;Git Intermediate&#8221; going in, and have a learned a ton in the preps, so there&#8217;s nothing like training people to sharpen your skills! The audience were all Java and Dotnet developers, [...]]]></description>
				<content:encoded><![CDATA[<p>Last week I sat down with a dozen people to run them through a basic <a href="http://www.bytecode.com.au/training/git-quickstart/">Git Training Course</a>. I would have said I was &#8220;Git Intermediate&#8221; going in, and have a learned a ton in the preps, so there&#8217;s nothing like training people to sharpen your skills!</p>
<p>The audience were all Java and Dotnet developers, most with some revision control experience, some with real-world Git experience. I developed the course with a more experienced Git developer, who was supporting me on the day with deep-dives and examples (which was awesome &#8211; love the dual trainer thing, good for the class too).</p>
<p><a href="http://blogs.bytecode.com.au/glen/wp-content/uploads/2012/11/Git-Training-Board.jpg"><img class="alignnone size-medium wp-image-829" title="Git Training Board" src="http://blogs.bytecode.com.au/glen/wp-content/uploads/2012/11/Git-Training-Board-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p>Let&#8217;s get Meta. So what did I learn about how people learn Git?</p>
<ul>
<li>We covered about 30 commands during the course of a 7 hour day (zoom in on the training board picture that we were walking through above), and I was surprised that I use nearly all of those commands every day (so the Git feature set is much broader than your typical SVN/CVS flow).</li>
<li>Git Internals are so &#8220;wafer-thin-below-the-surface&#8221; that you might as well teach how Git works from the start. Next time I&#8217;ll use a desk workflow with paper cards to discuss how DAGs hang together after the first module of playing. I like <a href="http://blip.tv/open-source-developers-conference/git-for-ages-4-and-up-4460524">what this guy did</a>, and I would like to try that with index cards.</li>
<li>Teaching people the Reflog early really helps them to get that things are very safe with Git, much safer than with anything else they&#8217;ve used &#8211; and that a commit really is immutable (regardless of what they hear about rewriting history/commits/etc). That knowledge actually gives you confidence to, well, rewrite history. <img src='http://blogs.bytecode.com.au/glen/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
<li>Remoting is really where people started to fall off the wagon. They could live with a staging area, but the idea of local and remote repos really needed a lot more exercises and a lot more experimenting. Pull/Fetch and diffing from master..origin/master&#8230; wat? Well.. Next round of courseware will spend more time on that. And more exercises.</li>
<li>Learning how Reset really works also requires a really solid mental model of the Git DAG. Next time I will spend more time on paper away from the terminal working through all this on index cards before we get lost in the weeds.</li>
<li>People were more comfortable with rebasing than I thought. In fact, interactive rebasing was totally fine, and rebasing master to branch seemed to have a pretty clear mental model for most people.</li>
<li>We taught everything through Git Bash, and I probably would offer <a href="https://github.com/dahlbyk/posh-git">Posh Git</a> as a good albeit slow Powershell alternative for the guys who were new to Unix.</li>
<li>Giving people concrete ideas on team Git workflows (such as <a href="http://scottchacon.com/2011/08/31/github-flow.html">GitHub Flow</a>) is really helpful when you have so much flexibility. Need to workshop that one a bit hard for next time.</li>
</ul>
<div>Anyways, once I fix up a few corrections to the notes we used on the day, I&#8217;ll post them here (not sure they&#8217;ll be very useful to you since I&#8217;m certainly no <a href="http://training.github.com/">Matt/Tim</a>, but it might give you ideas for exercises to introduce to your own teams).</div>
<div></div>
<div>Rebase early, and love the Reflog!</div>
<div></div>
<div><strong>Update:</strong> Slides below. Download them to get the PPT with the training notes on the speaker slides.</div>
<p><iframe src="http://www.slideshare.net/slideshow/embed_code/15258387" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen webkitallowfullscreen mozallowfullscreen> </iframe>
<div style="margin-bottom:5px"> <strong> <a href="http://www.slideshare.net/glen_a_smith/git-one-day-training-notes" title="Git One Day Training Notes" target="_blank">Git One Day Training Notes</a> </strong> from <strong><a href="http://www.slideshare.net/glen_a_smith" target="_blank">glen_a_smith</a></strong> </div>
]]></content:encoded>
			<wfw:commentRss>http://blogs.bytecode.com.au/glen/2012/11/13/reflections-on-running-a-git-course.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Testing UrlMappings params in Grails</title>
		<link>http://blogs.bytecode.com.au/glen/2012/11/02/testing-urlmappings-params-in-grails.html</link>
		<comments>http://blogs.bytecode.com.au/glen/2012/11/02/testing-urlmappings-params-in-grails.html#comments</comments>
		<pubDate>Thu, 01 Nov 2012 21:27:10 +0000</pubDate>
		<dc:creator>Glen</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>

		<guid isPermaLink="false">http://blogs.bytecode.com.au/glen/?p=816</guid>
		<description><![CDATA[I&#8217;m busy working on the UrlMappings section of Grails in Action (2nd Edition) and have been discovering a few interesting tidbits that don&#8217;t turn up in the docs (at least not that I know of, at time of writing). One of them relates to testing more complex UrlMapping setups. For instance, here are a couple [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;m busy working on the UrlMappings section of Grails in Action (<a href="http://www.manning.com/gsmith2/">2nd Edition</a>) and have been discovering a few interesting tidbits that don&#8217;t turn up in the docs (at least not that I know of, at time of writing).</p>
<p>One of them relates to testing more complex UrlMapping setups. For instance, here are a couple of interesting examples to get you thinking:</p>
<pre class="brush: groovy; gutter: true">class UrlMappings {

    static mappings = {
         // other mappings here...

        &quot;/timeline/chuck_norris&quot; {
            controller = &quot;post&quot;
            action = &quot;timeline&quot;
            id = &quot;chuck_norris&quot;
        }

        &quot;/users/$id&quot; {
            controller = &quot;post&quot;
            action = &quot;timeline&quot;
        }

    }
}</pre>
<p>So we have two mappings in place here. Both map to controller and action, with one setting a static id of &#8220;chuck_norris&#8221; and the other parsing the $id off the url. In both cases we end up inside the Post controller and fire off the timeline action.</p>
<p>To test this bad boy, we want to test the mapping to action and controller, but we also want to test the params that we have either (a) parsed out of the url; or (b) set within the mapping block.</p>
<p>The magic you need to know is that assertForwardUrlMapping takes an optional closure as the final parameter. Inside that closure, you assign the values to expect to receive, and UrlMappingsUnitTestMixin will do the heavy work of comparison for you. Enter the Spec&#8230;.</p>
<pre class="brush: groovy; gutter: true">import com.grailsinaction.PostController
import grails.test.mixin.Mock
import grails.test.mixin.TestFor
import spock.lang.Specification

@TestFor(UrlMappings)
@Mock(PostController)
class UrlMappingsSpec extends Specification {

    def &quot;Ensure basic mapping operations for user permalink&quot;() {

        expect:
        assertForwardUrlMapping(url, controller: expectCtrl, action: expectAction) {
            id = expectId
        }

        where:
        url                     | expectCtrl| expectAction  | expectId
        &#039;/users/glen&#039;           | &#039;post&#039;    | &#039;timeline&#039;    | &#039;glen&#039;
        &#039;/timeline/chuck_norris&#039;| &#039;post&#039;    | &#039;timeline&#039;    | &#039;chuck_norris&#039;
    }

}</pre>
<p>Just remember, the Closure takes a set of assignments (id = &#8216;abc&#8217;) not comparisons (id == &#8216;abc&#8217;) and you&#8217;re in business.</p>
<p>We have a truckload of tests like these in <a href="http://www.manning.com/gsmith2/">Grails In Action 2</a>, so if you&#8217;re into this style of experimenting, you&#8217;re going to enjoy reading the samples.</p>
<p>Go forth and test your complex mappings!</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.bytecode.com.au/glen/2012/11/02/testing-urlmappings-params-in-grails.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
