<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
    <channel>
        <title>Scott Leberknight - Blogs at Near Infinity</title>


        <link>http://www.nearinfinity.com/blogs/</link>
        <description>Employee Blogs</description>
        <language>en</language>
        <copyright>Copyright 2010</copyright>
        <lastBuildDate>Sun, 24 Jan 2010 23:14:35 -0500</lastBuildDate>
        <generator>http://www.sixapart.com/movabletype/</generator>
        <docs>http://www.rssboard.org/rss-specification</docs>
        
        <item>
            <title>Using Keynote Remote When There&apos;s No Wi-Fi Around</title>
            <description><![CDATA[ <p>I just bought <a href="http://appadvice.com/appnn/2009/01/review-keynote-remote/">Keynote Remote</a> for my iPhone. It is very simple, has the option to display presenter notes, and is absurdly simple to link to Keynote and start controlling presentations. What was a little more involved was that I wanted to use it regardless of whether there is a wireless network around or not. Since Keynote Remote requires a wi-fi connection here's what I'm doing to get around this little annoyance. Basically all you need to do is set up an ad-hoc wireless network with your Mac, and have your iPhone connect to that network. Voila! So, when there's no wireless network available, I just use my handy-dandy Verizon Wireless USB760 Modem to connect to the Internet, and I can still control presentations with Keynote Remote.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/using_keynote_remote_when_ther.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/using_keynote_remote_when_ther.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">iPhone</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">iphone</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">keynote</category>
            
            <pubDate>Sun, 24 Jan 2010 23:14:35 -0500</pubDate>
        </item>
        
        <item>
            <title>Hibernate Performance Tuning Part 2 Article Published</title>
            <description><![CDATA[  <p>I've just published the second article of a two-part series in the December 2009 <a href="http://www.nofluffjuststuff.com/home/magazine_subscribe?id=10">NFJS Magazine</a> on Hibernate Performance Tuning. Here's the abstract:</p>

<p><em>Tuning performance in Hibernate applications is all about reducing the number of database queries or eliminating them entirely using caching. In the first article in this two part series, you saw how to tune object retrieval using eager fetching techniques to optimize queries and avoid lazy-loads. In this second and final article, I'll show you how inheritance strategy affects performance, how to eliminate queries using the Hibernate second-level cache, and show some simple but effective tools you can use to monitor and profile your applications.</em></p>

<p>If you are using Hibernate and want to know more about how inheritance affects performance, how to use the second-level cache, and some simple monitoring and profiling techniques, check it out and let me know what you think. Note that NFJS Magazine does require a subscription.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/hibernate_performance_tuning_p_1.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/hibernate_performance_tuning_p_1.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Database</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Java</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">ORM</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Persistence</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">hibernate</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">java</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">ORM</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">performance</category>
            
            <pubDate>Mon, 21 Dec 2009 14:17:55 -0500</pubDate>
        </item>
        
        <item>
            <title>Making Cobertura Reports Show Groovy Code with Maven</title>
            <description><![CDATA[ <p>A recent project started out life as an all-Java project that used Maven as the build tool. Initially we used <a href="http://www.atlassian.com/software/clover/">Atlassian Clover</a> to measure unit test coverage. Clover is a great product for Java code, but unfortunately it only works with Java code because it works at the Java source level. (This was the case as of Spring 2009, and I haven't checked since then.) As we started migrating existing code from Java to Groovy and writing new code in Groovy, we started to lose data about unit test coverage because Clover does not understand Groovy code. To remedy this problem we switched from Clover to <a href="http://cobertura.sourceforge.net/">Cobertura</a>, which instruments at the bytecode level and thus works with Groovy code. Theoretically it would also work with any JVM-based language but I'm not sure whether or not it could handle something like Clojure or not.</p>

<p>In any case, we only cared about Groovy so Cobertura was a good choice. With the <a href="http://mojo.codehaus.org/cobertura-maven-plugin/">Cobertura Maven</a> plugin we quickly found a problem, which was that even though the code coverage was running, the reports only showed coverage for Java code, not Groovy. This blog shows you how to display coverage on Groovy code  when using Maven and the Cobertura plugin. In other words, I'll show how to get Cobertura reports to link to the real Groovy source code in Maven, so you can navigate Cobertura reports as you normally would.</p>

<p>The core problem is pretty simple, though it took me a while to figure out how to fix it. Seems to be pretty standard in Maven: I know what I want to do, but finding out how to do it is the <i>really</i> hard part. The only thing you need to do is tell Maven about the Groovy source code and where it lives. The way I did this is to use the Codehaus <a href="http://mojo.codehaus.org/build-helper-maven-plugin/">build-helper-maven-plugin</a> which has an add-source goal. The add-source goal does just what you would expect; it adds a specified directory (or directories) as a source directory in your Maven build. Here's how you use it in your Maven pom.xml file:</p>

<pre class="prettyprint">
&lt;plugin&gt;
    &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
    &lt;artifactId&gt;build-helper-maven-plugin&lt;/artifactId&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;phase&gt;generate-sources&lt;/phase&gt;
            &lt;goals&gt;
                &lt;goal&gt;add-source&lt;/goal&gt;
            &lt;/goals&gt;
            &lt;configuration&gt;
                &lt;sources&gt;
                    &lt;source&gt;src/main/groovy&lt;/source&gt;
                &lt;/sources&gt;
            &lt;/configuration&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt;
</pre>

<p>In the above code snippet, we're  using the "build-helper-maven-plugin" to add the src/main/groovy directory. That's pretty much it. Run Cobertura as normal, view the reports, and you should now see coverage on Groovy source code as well as Java.</p>
]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/making_cobertura_reports_show.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/making_cobertura_reports_show.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Groovy</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Java</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Testing</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">cobertura</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">groovy</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">java</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">maven</category>
            
            <pubDate>Tue, 15 Dec 2009 23:33:19 -0500</pubDate>
        </item>
        
        <item>
            <title>Hibernate Performance Tuning Part 1 Article Published</title>
            <description><![CDATA[ <p>I've just published an article in the November 2009 <a href="http://www.nofluffjuststuff.com/home/magazine_subscribe?id=9">NFJS Magazine</a> on Hibernate Performance Tuning. Here's the abstract:</p>

<p><em>Many developers treat Hibernate like a "black box" and assume it will simply "Do the Right Thing" when it comes to all things related to the underlying database. This is a faulty assumption because, while Hibernate is great at the mechanics of database interaction, it cannot and will likely not ever be able to figure out the specific details of your domain model and discern the most efficient and best performing data access strategies. In this first article of a two part series, I'll show you how to achieve better performance in your Hibernate applications by focusing on tuning object retrieval, which forms the basis of your "fetch plan" for finding and storing objects in the database.</em></p>

<p>If you are using Hibernate and want to know more about how to change how objects are fetched from the database, check it out and let me know what you think. Note that NFJS Magazine does require a subscription.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/hibernate_performance_tuning_p.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/hibernate_performance_tuning_p.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Database</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Java</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">ORM</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Persistence</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">hibernate</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">java</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">ORM</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">performance</category>
            
            <pubDate>Tue, 01 Dec 2009 19:29:07 -0500</pubDate>
        </item>
        
        <item>
            <title>Can Java Be Saved?</title>
            <description><![CDATA[ <h3>Java and Evolution</h3>

<p>The Java language has been around for a pretty long time, and in my view is now a stagnant language. I don't consider it <a href="http://codemonkeyism.com/java-dead/">dead</a> because I believe it will be around for probably decades if not longer. But it appears to have reached its evolutionary peak, and it doesn't look it's going to be evolved any further. This is not due to problems inherent in the language itself. Instead it seems the problem lies with Java's stewards (Sun and the JCP) and their unwillingness to evolve the language to keep it current and modern, and more importantly the goal to keep backward compatibility at all costs. Not just Sun, but also it seems the large corporations with correspondingly large investments in Java like IBM and Oracle aren't exactly chomping at the bit to improve Java. I don't even know if they think it even needs improvement at all. So really, the ultra-conservative attitude towards change and evolution is the problem with Java from my admittedly limited view of things.</p>

<p>That's why I don't hate Java. But, I do hate the way it has been treated by the people charged with improving it. It is clear many in the Java community want things like closures and a native property syntax but instead we got Project Coin. This, to me, is sad really. It is a shame that things like closures and native properties were not addressed in Java/JDK/whatever-it-is-called 7.</p>

<h3>Why Not?</h3>

<p>I want to know why Java can't be improved. We have concrete examples that it is possible to change a major language in major ways. Even in ways that break backward compatibility in order to evolve and improve. Out with the old, in with the new. Microsoft with C# showed that you can successfully evolve a language over time in major ways. For example C# has always had a property syntax but it now also has many features found in dynamically typed and functional languages such as type inference and, effectively, closures. With LINQ it introduced functional concepts. When C# added generics they did it correctly and retained the type information in the compiled IL, whereas Java used type-erasure and simply dropped the types from the compiled  bytecode. There is a great irony here: though C# began life about five or six years after Java, it not only has caught up but has surpassed Java in most if not all ways, and has continued to evolve while Java has become stagnant.</p>

<p>C# is not the only example. Python 3 is a major overhaul of the Python language, and it introduced breaking changes that are not backwards compatible. I believe they provide a migration tool to assist you should you want to move from the 2.x series to version 3 and beyond. Microsoft has done this kind of thing as well. I remember when they made Visual Basic conform to the .NET platform and introduced some rather gut wrenching (for VB developers anyway) changes, and they also provided a tool to aid the transition. One more recent example is Objective-C which has experienced a resurgence in importance mainly because of the iPhone. Objective-C has been around longer than all of Java, C#, Ruby, Python, etc. since the 1980s. Apple has made improvements to Objective-C and it now sports a way to define and synthesize properties and most recently added blocks (effectively closures). If a language that pre-dates Java (Python also pre-dates Java by the way) can evolve, I just don't get why Java can't.</p>

<p>While it is certainly possible to remain on older versions of software, forcing yourself to upgrade can be a Good Thing, because it ensures you don't get the "COBOL Syndrome" where you end up with nothing but binaries that have to run on a specific hardware platform forever and you are trapped until you rewrite or you go out of business. The other side of this, of course, is that organizations don't have infinite time, money, and resources to update every single application. Sometimes this too can be good, because it forces you to triage older systems, and possibly consolidate or outright eliminate them if they have outlived their usefulness. In order to facilitate large transitions, I believe it is very important to use tools that help automate the upgrade process, e.g. tools that analyze code and fix it if possible (reporting all changes in a log) and which provide warnings and guidance when a simple fix isn't possible.</p>

<h3>The JVM Platform</h3>

<p>Before I get into the changes I'd make to Java to make it not feel like I'm developing with a straightjacket on while having to type masses of unnecessary boilerplate code, I want to say that I think the JVM is a great place to be. Obviously the JVM itself facilitates developing all kinds of languages as evidenced by the huge number of languages that run on the JVM. The most popular ones and most interesting ones these days are probably JRuby, Scala, Groovy, and Clojure though there are probably hundreds more. So I suppose you could make an argument that Java doesn't need to evolve any more because we can simply use a more modern language that runs on the JVM.</p>

<p>The main problem I have with that argument is simply that there is already a ton of Java code out there, and there are many organizations who are simply not going to allow other JVM-based languages; they're going to stick with Java for the long haul, right or wrong. This means there is a good chance that even if you can manage convince someone to try writing that shiny new web app using Scala and its Lift framework,  JRuby on Rails, Grails, or Clojure, chances are at some point you'll also need to maintain or enhance existing large Java codebases. Wouldn't you like to be able to first upgrade to a version of Java that has closures, native property syntax, method/property handles, etc?</p>

<p>Next I'll choose what would be my top three choices to make Java much better immediately.</p>

<h3>Top Three Java Improvements</h3>

<p>If given the chance to change just three things about Java to make it better, I would choose these:</p>

<ul>
<li>Remove checked exceptions</li>
<li>Add closures</li>
<li>Add formal property support</li>
</ul>

<p>I think these three changes along would make coding in Java much, much better. Let's see how.</p>

<h4>Remove Checked Exceptions</h4>

<p>By removing checked exceptions you eliminate a ton of boilerplate try/catch clauses that do nothing except log a message, wrap and re-throw as a RuntimeException, pollute the API with throws clauses all over the place, or worst of all empty catch blocks that can cause very subtle and evil bugs. With unchecked exceptions, developers still have the option to catch exceptions that they can actually handle. It would be interesting to see how many times in a typical Java codebase people actually handle exceptions and do something at the point of exception, or whether they simply punt it away for the caller to handle, who in turn also punts, and so forth all the way up the call stack until some global handler catches it or the program crashes. If I were a betting man, I'd bet a lot of money that for most applications, developers punt the vast majority of the time. So why force people to handle something they cannot possible handle?</p>

<h4>Add Closures</h4>

<p>I specifically listed removing checked exceptions first, because to me it is the first step to being able to have a closure/block syntax that isn't totally horrendous. If you remove checked exceptions, then adding closures would seem to be much easier since you don't need to worry at all about what exceptions could possibly be thrown and there is obviously no need to declare exceptions. Closures/blocks would lead to better ability to handle collections, for example as in Groovy but in Java you would still have types (note I'm also using a literal property syntax here):</p>

<pre class="prettyprint">
// Find all people whose last name is "Smith"
List&lt;Person&gt; peeps = people.findAll { Person person -> person.lastName.equals("Smith");   } 
</pre>

or

<pre class="prettyprint">
// Create a list of names by projecting the name property of a bunch of Person objects
List&lt;String&gt; names = people.collect { Person person -> person.name; }
</pre>

<p>Not quite as clean as Groovy but still much better than the for loops that would traditionally be required (or trying to shoehorn functional-style into Java using the <a href="http://commons.apache.org/collections/">Jakarta Commons Collections</a>  or <a href="http://code.google.com/p/google-collections/">Google Collections</a>). Removal of checked exceptions would allow, as mentioned earlier, the block syntax to not have to deal with declaring exceptions all over the place. Having to declare checked exceptions in blocks makes the syntax worse instead of better, at least when I saw the various closure proposals for Java/JDK/whatever 7 which did not get included. Requiring types in the blocks is still annoying, especially once you get used to Ruby and Groovy, but it would be passable.</p>

<h4>Native Property Syntax</h4>

<p>The third change should do essentially what Groovy for properties does but should introduce a "property" keyword (i.e. don't rely on whether someone accidentally put an access modifier in there as Groovy does). The syntax could be very clean:</p>

<pre class="prettyprint">
property String firstName;
property String lastName;
property Date dateOfBirth;
</pre>

<p>The compiler could automatically generate the appropriate getter/setter for you like Groovy does. This obviates the need to manually code the getter/setter. Like Groovy you should be able to override either or both. It de-clutters code enormously and removes a ton of lines of silly getter/setter code (plus JavaDocs if you are actually still writing them for every get/set method). Then you could reference properties as you would expect: person.name is the "getter" and person.name = "Fred" is the "setter." Much cleaner syntax, way less boilerplate code. By the way, if someone used the word "property" in their code, i.e. as a variable name, it is just not that difficult to rename refactor, especially with all the advanced <a href="http://www.jetbrains.com/idea/">IDEs</a> in the Java community that do this kind of thing in their sleep.</p>

<p>Lots of other things could certainly be done, but if just these three were done I think Java would be much better off, and maybe it would even come into the 21st century like Objective-C. (See the very long but very good <a href="http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars">Ars Technica Snow Leopard review</a> for information on Objective-C's new <a href="http://arstechnica.com/apple/reviews/2009/08/mac-os-x-10-6.ars/10#blocks">blocks</a> feature.)</p>

<h3>Dessert Improvements</h3>

<p>If (as I suspect they certainly will :-) ) Sun/Oracle/whoever takes my suggestions and makes these changes and improves Java, then I'm sure they'll want to add in a few more for dessert. After the main course which removes checked exceptions, adds closures, and adds native property support, dessert includes the following:</p>

<ul>
<li>Remove type-erasure and clean up generics</li>
<li>Add property/method handles</li>
<li>String interpolation</li>
<li>Type inference</li>
<li>Remove "new" keyword
</ul>

<h4>Clean Up Generics</h4>

<p>Generics should simply not remove type information when compiled. If you're going to have generics in the first place, do it correctly and stop worrying about backward compatibility. Keep type information in the bytecode, allow reflection on it, and allow me to instantiate a "new T()" where T is some type passed into a factory method, for example. I think an improved generics implementation could basically copy the way C# does it and be done.</p>

<h4>Property/Method Handles</h4>

<p>Property/method <a href="http://blogs.sun.com/jrose/entry/method_handles_in_a_nutshell">handles</a> would allow you to reference a property or method directly. They would make code that now must use strings strongly typed and refactoring-safe (IDEs like IntelliJ already know how to search in text and strings but can never be perfect) much nicer. For example, a particular pet peeve of mine and I'm sure a lot of other developers is writing Criteria queries in Hibernate. You are forced to reference properties as simple strings. If the lastName property is changed to surname then you better make sure to catch all the places the String "lastName" is referenced. So you could replace code like this:</p>

<pre class="prettyprint">
session.createCriteria(Person.class)
	.add(Restrictions.eq("lastName", "Smith")
	.addOrder(Order.asc("firstName")
	.list();
</pre>

<p>with this using method/property handles:</p>

<pre class="prettyprint">
session.createCriteria(Person.class)
	.add(Restrictions.eq(Person.lastName, "Smith")
	.addOrder(Order.asc(Person.firstName)
	.list();
</pre>

<p>Now the code is strongly-typed and refactoring-safe. JPA 2.0 tries mightily to overcome having strings in the new criteria query API  with its metamodel. But I find it pretty much appalling to even look at, what with having to create or code-generate a separate "metamodel" class which you reference like "_Person.lastName" or some similar awful way. This metamodel class lives only to represent properties on your real model object for the sole purpose of making JPA 2.0 criteria queries strongly typed. It just isn't worth it and is total overkill. In fact, it reminds me of the bad-old days of rampant over-engineering in Java (which apparently is still alive and well in many circles but I try to avoid it as best I can). The right thing is to fix the language, not to invent something that adds yet more boilerplate and more complexity to an already overcomplicated ecosystem.</p>

<p>Method handles could also be used to make calling methods using reflection much cleaner than it currently is, among other things. Similarly it would make accessing properties via reflection easier and cleaner. And with only unchecked exceptions you would not need to catch the four or five kinds of exceptions reflective code can throw.</p>

<h4>String Interpolation</h4>

<p>String interpolation is like the sorbet that you get at fancy restaurants to cleanse your palate. This would seem to be a no-brainer to add. You could make code like:</p>

<pre class="prettyprint">
log.error("The object of type  ["
    + foo.getClass().getName()
    + "] and identifier ["
    + foo.getId()
    + "] does not exist.", cause);
</pre>

<p>turn into this much more palatable version (using the native property syntax I mentioned earlier):</p>

<pre class="prettyprint">
log.error("The object of type [${foo.class.name}] and identifier [${foo.id}] does not exist.", cause);
</pre>

<h4>Type Inference</h4>

<p>I'd also suggest adding type inference, if only for local variables like C# does. Why do we have to repeat ourselves? Instead of writing:</p>

<pre class="prettyprint">
Person person = new Person();
</pre>

<p>why can't we just write:</p>

<pre class="prettyprint">
var person = new Person();
</pre>

<p>I have to believe the compiler and all the tools are smart enough to infer the type from the "new Person()". Especially since other strongly-typed JVM languages like Scala do exactly this kind of thing.</p>

<h4>Elminate "new"</h4>

<p>Last but not least, and actually not the last thing I can think of but definitely the last I'm writing about here, let's get rid of the "new" keyword and either go with Ruby's new <i>method</i> or Python's constructor syntax, like so:</p>

<pre class="prettyprint">
// Ruby-like new method
var person = Person.new()

// or Python-like construction
var person = Person()
</pre>

<p>This one came to me recently after hearing <a href="http://en.wikipedia.org/wiki/Bruce_Eckel">Bruce Eckel</a> give an excellent talk on language evolution and archaeology. He had a ton of really interesting examples of why things are they way they are, and how Java and other languages like C++ evolved from C. One example was the reason for "new" in Java. In C++ you can allocate objects on the stack or the heap, so there is a stack-based constructor syntax that does not use "new" while the heap-based constructor syntax uses the "new" operator. Even though Java only has heap-based object allocation, it retained the "new" keyword which is not only boilerplate code but also makes the entire process of object construction pretty much immutable: you cannot change anything about it nor can you easily add hooks into the object creation process.</p>

<p>I am not an expert at all in the low-level details, and Bruce obviously knows what he is <a href="http://www.amazon.com/Thinking-C-2-Practical-Programming/dp/0130353132/">talking</a> <a href="http://www.amazon.com/Thinking-Java-4th-Bruce-Eckel/dp/0131872486/">about</a> way more than I do, but I can say that I believe the Ruby and Python syntaxes are not only nicer but more internally consistent, especially in the Ruby case because there is no special magic or sauce going on. In Ruby, new is just a method, on a class, just like everything else.</p>

<h3>Conclusion to this Way Too Long Blog Entry</h3>

<p>I did not actually set out to write a blog whose length is worthy of a <a href="http://blogs.tedneward.com/">Ted Neward</a> blog. It just turned out that way. (And I do in fact like reading Ted's long blogs!) Plus, I found out that <a href="http://en.wikipedia.org/wiki/Speculative_fiction">speculative fiction</a> can be pretty fun to write, since I don't think pretty much any of these things are going to make it into Java anytime soon, if ever, and I'm sure there are lots of people in the Java world who hate things like Ruby won't agree anyway.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/can_java_be_saved.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/can_java_be_saved.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Java</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">C#</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">clojure</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">closure</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">groovy</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">java</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">python</category>
            
            <pubDate>Mon, 09 Nov 2009 15:23:10 -0500</pubDate>
        </item>
        
        <item>
            <title>Several Must Have Firebug-Related Firefox Extensions</title>
            <description><![CDATA[ <p>Last week while doing the usual (web development stuff) I discovered a few Firefox extensions I didn't even know I was missing until I found them by accident. The "accident" happened while adding Firebug to a Firefox that was running in a VMWare Fusion Windows virtual machine on which I was testing in, gasp, Windows. I went to find add-ons and searched for Firebug. And up came not only <a href="http://getfirebug.com/">Firebug</a> but also results for <a href="http://www.softwareishard.com/blog/firecookie/">Firecookie</a>, <a href="http://robertnyman.com/firefinder/">Firefinder</a>, <a href="http://robertnyman.com/inline-code-finder/">Inline Code Finder for Firebug</a>, and <a href="http://tools.sitepoint.com/codeburner/firefox">CodeBurner for Firebug</a>.</p>

<p>Of course everyone doing web development uses Firebug (or really should anyway) since it rules. But these other extensions provide some <i>really</i> nice functionality and complement Firebug perfectly. Here's a quick run down:</p>

<h3>Firecookie</h3>

<p>Firecookie lets you see all the cookies for a site, add new ones, remove existing cookies, etc. It gives useful information about each cookie like the name, value, raw value (if URI-encoded), domain, size, path, expiration, and security. Very cool.</p>

<style type="text/css">
img.border {
   margin-bottom: 10px;
   border: 1px solid #021a40;
}
</style>

<img class="border" src="http://www.sleberknight.com/blog/sleberkn/resource/firecookie.png" alt="Firecookie Firefox Add-On" title="Firecookie Firefox Add-On"/>

<h3>Firefinder</h3> 

<p>Firefinder for Firebug lets you search for elements on a page using either CSS expressions or an XPath query. In the list of matching elements, you can expand each result, inspect the element by clicking the "Inspect" link, or click "FriendlyFire" which will copy the content you're looking at and post it up to <a href="http://jsbin.com/">JS Bin</a>. (Be careful with this one if you have code you'd rather not have going up over the wire to a different web site.) Firefinder also puts a dashed border around each matching element it found. As you hover over search results, it highlights the matching element in the page. This is really useful when you want to find all elements matching a CSS expression or when you'd like to use XPath to find specific elements. Nice.</p>

<img class="border" src="http://www.sleberknight.com/blog/sleberkn/resource/firefinder.png" alt="Firefinder Firefox Add-On" title="Firefinder Firefox Add-On"/>

<h3>Inline Code Finder for Firebug</h3>

<p>The Inline Code Finder does just that. It finds inline CSS styles, JavaScript links, and inline events, and reports the number of each of these in its results pane. Even better, it highlights each of these problems on the page  you are viewing with a thick red border, and as you hover over them it shows you what the problem is in a nicely tooltip. This is really nice to help you become less obtrusive by writing more unobtrusive JavaScript and avoiding inline styles. For older sites or sites that weren't designed with "unobtrusivity" in mind though, be warned that there might be a lot of red on the page!</p>

<img class="border" src="http://www.sleberknight.com/blog/sleberkn/resource/inlinecodefinder.png" alt="Inline Code Finder Firefox Add-On" title="Inline Code Finder Firefox Add-On"/>

<h3>CodeBurner for Firebug</h3>

<p>CodeBurner for Firebug provides an inline HTML and CSS reference within Firebug. It allows you to search for HTML elements or CSS styles and shows a definition and an example. It also provides links to the awesome <a href="http://www.sitepoint.com/">Sitepoint</a> reference and even to the Sitepoint live demos of the feature you are learning about. This is so unbelievably useful to have a HTML and CSS references directly within Firebug it isn't even funny. Thanks Sitepoint.</p>

<img class="border" src="http://www.sleberknight.com/blog/sleberkn/resource/codeburner.png" alt="CodeBurner Firefox Add-On" title="CodeBurner Firefox Add-On"/>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/several_must_have_firebug-rela.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/several_must_have_firebug-rela.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Web Development</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">firefox firebug</category>
            
            <pubDate>Mon, 28 Sep 2009 12:47:51 -0500</pubDate>
        </item>
        
        <item>
            <title>Migrating Macs When You Use FileVault</title>
            <description><![CDATA[ <p>Recently I got a brand spankin new MacBook Pro (MBP) to replace my three-year-old one. One of the things I did <i>not</i> want to deal with is setting up a new computer from scratch and reconfiguring and reinstalling everything I already had on my old MBP. I have things pretty-well organized, I know where things are, and I remember when I rebuilt from scratch from Tiger to Leopard I lost a bunch of settings and such because I hadn't used any kind of migration software. Not this time. This time I wanted my new computer to essentially be my old computer, but with more memory and faster with no hassles.</p>

<p>There are a few options I considered. First, simply take a SuperDuper backup and restore directly to the new MBP. I researched this a lot, talked to people who've done this both successfully and unsuccessfully, and  talked to a Genius at the Apple store. The second option was to use the Migration Assistant to transfer from old to new. After all the research, I decided against restoring from SuperDuper for several reasons. First, it seemed to be hit or miss: some people reported success and some did not. Second, and more importantly, I was transferring from a circa August 2006 MBP, in fact one of the first revs that had the Intel chips inside, to a circa June 2009 MBP with the new trackpad and all the other updated jazz. I was mostly concerned that there could have been enough difference between the old and new computers' hardware and software drivers and that a direct restore would not contain up-to-date drivers and whatever else that could screw things up. So I chose to explore using Migration Assistant, which promised a very easy transfer of all files and settings.</p>

<p>So then I ran into the first  snag, which is that Migration Assistant does not transfer File Vault-ed user accounts, and I happen to use FileVault. Doh. So I thought, "OK no problem I'll simply turn off FileVault on the old machine first." Except that I only had about 7GB of space left on my hard drive, and turning FileVault off needs about as much free space as your home directory currently takes up. So if my home directory is currently 50GB, then I need about 50GB free. Double Doh, because I didn't have that kind of space! To solve all these problems, here is what I did, for anyone else who might be trying to do the same thing:</p>

<h3>Step 1 - Backup Original Mac</h3>

<p>Make a SuperDuper backup of the old MBP onto a portable external hard drive. (I actually made two copies on two different external hard drives, just in case something got screwed up later.) The external drive should contain plenty of space, enough so you can turn off FileVault on your home directory.</p>

<h3>Step 2 - Turn off FileVault on External Drive</h3>

<p>Restart the old Mac and boot from the SuperDuper backup. (You hold down the option key during startup to get the screen where you can choose to boot from the Mac hard drive or the SuperDuper backup on the external drive.) Note at this point you are now running Mac OS X on the external hard drive. Log into the FileVault-ed account, go to System Preferences, and turn FileVault off. (This is why you needed to make sure the external drive has enough space to turn off FileVault, since you are turing it off there, not on your Mac's hard drive!) Now go grab something to eat and/or watch a movie as this step can take a few hours depending on how much data you have.</p>

<p>Once complete, log out and shut down the external drive. You are now ready to transfer.</p>

<h3>Step 3 - Prepare for Migration Assistant on New Mac</h3>

<p>Log into your new Mac, and connect the external drive that contains the freshly un-FileVault-ed SuperDuper bootable backup of the original Mac. If you or someone else already setup a new user account on the new Mac <i>that has the same username as your old account does</i>, then create a new account with Administrator privileges (e.g. "MigrationAccount") and then delete the account that you will be transferring to. For example, if your old Mac account username was "bsmith" and the new Mac has an account with the same username, remove the "bsmith" account on the new Mac. Otherwise when you attempt the migration you might receive the following message like I did the first time I tried: "There is an existing user account with the same name as an account you are transferring." This wouldn't have been an issue, except that the option to replace the account was <i>disabled</i> and so Migration Assistant was refusing to overwrite it. Thus you should delete it first.</p>

<h3>Step 4 - Run Migration Assistant</h3>

<p>On the new Mac, run Migration Assistant and answer the questions. You'll be transferring from the external SuperDuper backup to the new Mac. The questions are easy and straightforward. Go grab something to drink or watch some TV, as it'll take a while to transfer all your old files and settings from the external drive to the new Mac. I'll just assume everything went well, because it did for me. If something went wrong, well, I don't have answers other than maybe to try, try, try again from scratch.

<h3>Step 5 - Turn FileVault Back On</h3>

<p>On the new Mac, turn FileVault on for the newly migrated account, e.g. if the "bsmith" account previously had FileVault on, then login as "bsmith" and turn on FileVault in System Preferences. Tick tock. More waiting as Mac OS X encrypts all the data in your home directory. Once this process completes, your new Mac should be pretty much the same as your old Mac, with all the same files and settings like Desktop, Screen Saver, etc. and with all your applications transferred successfully. And you are back up running with FileVault enabled.</p>

<h3>Step 6 - Secure Erase External Hard Drive</h3>

<p>At this point you have the new Mac setup with FileVault, and the old Mac still has FileVault on as well since you migrated from the external drive. But, the external drive now has unencrypted data sitting around since you turned FileVault off on it. Open up Disk Utility and do a <a href="http://support.apple.com/kb/TA24002?viewlocale=en_US">secure erase</a> of the un-FieVaulted external drive. Depending on which option you choose, e.g. "Zero Out Data", "7-Pass Erase", "35-Pass Erase", etc., the erase process can take a <i>long</i> time, as in <i>days</i>.  In other words, a 7- pass write overwrites every part of the disk 7 times to sanitize it and make recovery of the unencrypted information much harder, and takes 7 times longer than just zeroing out the data, which writes zeroes all over data on the disk.</p>

<p>I only did a zero out of the data, because I knew I was going to immediately overwrite that external drive with a new SuperDuper backup once I was done. If you need more insurance than that, a 7-pass erase confirms to the <a href="http://en.wikipedia.org/wiki/DOD_5220.22-M">DoD 5220.22-M</a> specification which is probably good enough. (Actually I started out using 7-pass erase until I saw it was going to take a day or two, and then I got a tad lazy and just did the zero out. Perhaps that is bad, but I didn't feel like waiting that long, and it's not like I have data for 100,000 employees on my hard drive in an Excel spreadsheet anyway. Just a lot of code and presentations and such, really.)</p>

<h3>Step 7 - Backup New Mac</h3>

<p>Make a fresh SuperDuper backup of the new Mac.</p>

<h3>Coda</h3>

<p>Although all the above sounds like it took a long time, the waiting and time was mostly due to having to turn FileVault off and then on and doing the secure erase.  Migration Assistant itself takes a fair amount of time but is totally worth it. Overall the entire process from start to finish on my old MBP with a 100GB hard drive containing only 7GB free space took between five and six hours, which is way less time than if I had tried to start over from scratch with the new Mac. I do wonder why Apple cannot just allow Migration Assistant to transfer accounts with FileVault enabled, because then pretty much all you'd need to do is run Migration Assistant directly, and you wouldn't need to go through all the  drama.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/migrating_macs_when_you_use_fi.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/migrating_macs_when_you_use_fi.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Mac OS X</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">FileVault</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">Mac OS X</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">migration</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">superduper</category>
            
            <pubDate>Mon, 21 Sep 2009 12:45:00 -0500</pubDate>
        </item>
        
        <item>
            <title>Sorting Collections in Hibernate Using SQL in @OrderBy</title>
            <description><![CDATA[<p>When you have collections of associated objects in domain objects, you generally want to specify some kind of default sort order. For example, suppose I have domain objects <code>Timeline</code> and <code>Event</code>:</p>

<pre class="prettyprint">
@Entity
class Timeline {

    @Required 
    String description

    @OneToMany(mappedBy = "timeline")
    @javax.persistence.OrderBy("startYear, endYear")
    Set&lt;Event&gt; events
}

@Entity
class Event {

    @Required
    Integer startYear

    Integer endYear

    @Required
    String description

    @ManyToOne
    Timeline timeline
}
</pre>

<p>In the above example I've used the standard JPA (Java Persistence API) <code>@OrderBy</code> annotation which allows you to specify the order of a collection of objects via object properties, in this example a <code>@OneToMany</code> association .  I'm ordering first by <code>startYear</code>  in ascending order and then by <code>endYear</code>, also in ascending order. This is all well and good, but note that I've specified that only the start year is required. (The <a href="http://www.nearinfinity.com/blogs/scott_leberknight/validating_domain_objects_in_hibernate2.html">@Required</a> annotation is a custom Hibernate Validator annotation which does exactly what you would expect.)  How are the events ordered when you have several events that start in the same year but some of them have no end year? The answer is that it depends on how your database sorts null values by default. Under Oracle 10g nulls will come last. For example if two events both start in 2001 and one of them has no end year, here is how they are ordered:</p>

<pre class="prettyprint">
2001 2002  Some event
2001 2003  Other event
2001       Event with no end year
</pre>

<p>What if you want to control how null values are ordered so they come first rather than last? In Hibernate there are several ways you could do this. First, you could use the Hibernate-specific <code>@Sort</code> annotation to perform in-memory (i.e. not in the database) sorting, using natural sorting or sorting using a <code>Comparator</code> you supply. For example, assume I have an <code>EventComparator</code> helper class that implements <code>Comparator</code>. I could change <code>Timeline</code>'s collection of events to look like this:</p>

<pre class="prettyprint">
@OneToMany(mappedBy = "timeline")
@org.hibernate.annotations.Sort(type = SortType.COMPARATOR, comparator = EventCompator)
 Set&lt;Event&gt; events
</pre>

<p>Using <code>@Sort</code>  will perform sorting in-memory once the collection has been retrieved from the database. While you can certainly do this and implement arbitrarily complex sorting logic, it's probably better to sort in the database when you can. So we now need to turn to <i>Hibernate's</i> <code>@OrderBy</code> annotation, which lets you specify a <i>SQL fragment</i> describing how to perform the sort. For example, you can change the events mapping to :</p>

<pre class="prettyprint">
@OneToMany(mappedBy = "timeline")
@org.hibernate.annotations.OrderBy("start_year, end_year")
 Set&lt;Event&gt; events
</pre>

<p>This sort order is the same as using the JPA <code>@OrderBy</code> with "startYear, endYear" sort order. But since you write actual SQL in Hibernate's <code>@OrderBy</code> you can take advantage of whatever features your database has, at the possible expense of portability across databases. As an example, Oracle 10g supports using a syntax like "order by start_year, end_year nulls first" to order null end years before non-null end years. You could also say "order by start_year, end year nulls last" which sorts null end years last as you would expect. This syntax is probably not portable, so another trick you can use is the NVL function, which is supported in a bunch of databases. You can rewrite <code>Timeline</code>'s collection of events like so:</p>

<pre class="prettyprint">
@OneToMany(mappedBy = "timeline")
@org.hibernate.annotations.OrderBy("start_year, nvl(end_year , start_year)")
 Set&lt;Event&gt; events
</pre>

<p>The expression "nvl(end_year , start_year)" simply says to use <code>end_year</code> as the sort value if it is not null, and <code>start_year</code> if it is null. So for sorting purposes you end up treating <code>end_year</code> as the same as the <code>start_year</code> if <code>end_year</code> is null. In the contrived example earlier, applying the nvl-based sort using Hibernate's <code>@OrderBy</code> to specify SQL sorting criteria, you now end with the events sorted like this:</p>

<pre class="prettyprint">
2001       Event with no end year
2001 2002  Some event
2001 2003  Other event
</pre>

<p>Which is what you wanted in the first place. So if you need more complex sorting logic than what you can get out of the standard JPA <code>@javax.persistence.OrderBy</code>, try one of the Hibernate sorting options, either <code>@org.hibernate.annotations.Sort</code> or <code>@org.hibernate.annotations.OrderBy</code>. Adding a SQL fragment into your domain class isn't necessarily the most <i>elegant</i> thing in the world, but it might be the most <i>pragmatic</i> thing.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/sorting_collections_in_hiberna.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/sorting_collections_in_hiberna.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Java</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">database</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">hibernate</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">java</category>
            
            <pubDate>Tue, 15 Sep 2009 12:40:00 -0500</pubDate>
        </item>
        
        <item>
            <title>Groovification</title>
            <description><![CDATA[ <p>Last week I tweeted about groovification, which is defined thusly:</p>

<p><i>groovification.</i> noun. the process of converting java source code into groovy source code (usually done to make development more fun)</p>

<p>On my main day-to-day project, we've been writing unit tests in Groovy for quite a while now, and recently we decided to start implementing new code in Groovy rather than Java. The reason for doing this is to gain more flexibility in development, to make testing easier (i.e. in terms of the ability to mock dependencies in a trivial fashion), to eliminate a lot of Java boilerplate code and thus write less code, and of course to make developing more fun. It's not that I hate Java so much as I feel Java simply isn't innovating anymore and hasn't for a while, and isn't adding features that I simply don't want to live without anymore such as closures and the ability to do metaprogramming when I need to. In addition, it isn't removing features that I don't want, such as checked exceptions. If I know, for a fact, that I can handle an exception, I'll handle it appropriately. Otherwise, when there's nothing I can do anyway, I want to let the damn thing propagate up and just show a generic error message to the user, log the error, and send the admin team an email with the problem details.</p>

<p>This being, for better or worse, a Maven project, we've had some interesting issues with mixed compilation of Java and Groovy code. The <a href="http://groovy.codehaus.org/">GMaven plugin</a> is easy to install and works well but currently has some outstanding issues related to Groovy stub generation, specifically it cannot handle <a href="http://jira.codehaus.org/browse/MGROOVY-108">generics</a> or <a href="http://jira.codehaus.org/browse/MGROOVY-109">enums</a> properly right now. (Maybe someone will be less lazy than me and help them fix it instead of complaining about it.) Since many of our classes use generics, e.g. in service classes that return domain objects, we currently are not generating stubs. We'll convert existing classes and any other necessary dependencies to Groovy as we make updates to Java classes, and we are implementing new code in Groovy. Especially in the web controller code, this becomes trivial since the controllers generally depend on other Java and/or Groovy code, but no other classes depend on the controllers. So starting in the web tier seems to be a good choice. Groovy combined with implementing controllers using the Spring @MVC annotation-based controller configuration style (i.e. no XML configuration), is making the controllers <i>really</i> thin, lightweight, and easy to read, implement, and test.</p>

<p>I estimate it will take a while to fully convert all the existing Java code to Groovy code. The point here is that we are doing it piecemeal rather than trying to do it all at once. Also, whenever we convert a Java file to a Groovy one, there are a few basics to make the classes Groovier without going totally overboard and spending loads of time. First, once you've used <a href="http://www.jetbrains.com/idea/">IntelliJ's</a> move refactoring to move the .java file to the Groovy source tree (since we have src/main/java and src/main/groovy) you can then use IntelliJ's handy-dandy "Rename to Groovy" refactoring. In IntelliJ 8.1 you need to use the "Search - Find Action" menu option or keystroke and type "Rename to..." and select "Rename to Groovy" since they goofed in version 8 and that option was left off a menu somehow. Once that's done you can do a few simple things to make the class a bit more groovy. First, get rid of all the semi-colons. Next, replace getter/setter code with direct property access. Third, replace for loops with "each"-style internal iterators when you don't need the loop index and "eachWithIndex" where you do. You can also get rid of some of the redundant modifiers like "public class" since that is the Groovy default. That's not too much at once, doesn't take long, and makes your code Groovier. Over time you can do more groovification if you like.</p>

<p>The most common gotchas I've found have to do with code that uses anonymous or inner classes since Groovy doesn't support those Java language features. In that case you can either make a non-public named class (and it's OK to put it in the same Groovy file unlike Java as long as it's not public) or you can refactor the code some other way (using your creativity and expertise since we are not <a href="http://www.nearinfinity.com/blogs/scott_leberknight/thinking_matters.html">monkeys</a>, right?). This can sometimes be a pain, especially if you are using a lot of them. So it goes. (And yes, that is a <a href="http://en.wikipedia.org/wiki/Slaughterhouse-Five">Slaughterhouse Five</a> reference.)</p>

<p>Happy groovification!</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/groovification.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/groovification.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Groovy</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Java</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">gmaven</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">groovy</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">java</category>
            
            <pubDate>Mon, 04 May 2009 17:22:38 -0500</pubDate>
        </item>
        
        <item>
            <title>Thinking Matters</title>
            <description><![CDATA[ <p>Aside from the fact that <a href="http://www.forbes.com/2009/04/29/java-oracle-sun-technology-internet-infrastructure-java.html">Oracle's Java Problem</a> contains all kinds of factual and other errors (see the comments on the post) this sentence caught my eye in particular when referring to Java being "quite hard to work with" - "Then, as now, you needed to be a highly trained programmer to make heads or tails of the language."</p>

<p>What's the issue here? That Java is hard to work with? Perhaps more specifically, not just Java but perhaps the artificial complexity in developing "Enterprise" applications in Java? Nope. The problem is that this type of thinking epitomizes the attitude that business people and other "professionals" tend to have about software development in general, in that they believe it is or should be easy and that it is always the tools and rogue programmers that are the problem. Thus, with more and better tools, they reason, there won't be a need for skilled developers and the monkey-work of actually programming could be done by, well, <a href="http://www.newtechusa.com/PPI/main.asp">monkeys</a>.</p>

<p>I believe software development is one of the hardest activities humans currently do, and yes I suppose I do have some bias since I am a developer. Also contrary to what many people think, there is both art and engineering involved, and any given problem can be solved in an almost infinite variety of ways. Unlike more established disciplines that have literally been around for hundreds or thousands of years (law, medicine, accounting, architecture, certain branches of engineering like civil, etc.), the software industry hasn't even reached the century mark yet! As a result there isn't any kind of consensus whatsoever about a completely standardized "body of knowledge" and thus there isn't an industy-recognized set of standard exams and boards like you find in the medical and law professions for example. (That topic is for a future post.)</p>

<p>One thing that is certain is that software development involves logic, and thus people who can solve problems using logic will always be needed, whether the primary medium stays in textual format (source code) or whether it evolves into some different representation like <a href="http://martinfowler.com/bliki/IntentionalSoftware.html">Intentional Software</a> is trying to do. So the statement from the article that "you needed to be a highly trained programmer to make heads or tails of the language" is always going to be true in software development. More generally, highly skilled people are needed in any complex endeavor, and attempts to dumb dumb complex things will likely not succeed in any area, not just software development. Would you trust someone to perform surgery on you so long as they have a "Dummies Guide to Surgery" book? Or someone to represent you in court who stayed at a Holiday Inn Express last night?</p>

<p>I hypothesize that things are becoming more complex as time moves on, not less. I also propose that unless we actually succeed in building <a href="http://www.scifi.com/battlestar/">Cylons</a> who end up wiping us all out or enslaving us, we will never reach a point where we don't need people to actually think and use logic to solve problems. So even though many business-types would love to be able to hire a bunch of monkeys and pay them $0.01 per day to develop software, those who actually realize that highly skilled people are an asset and help their bottom line, and treat them as such, are the ones who will come out on top, because they will smash their competitors who think of software/IT purely as a cost center and not a profit center.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/thinking_matters.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/thinking_matters.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">General</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Java</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">cylon</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">logic</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">programming</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">thinking</category>
            
            <pubDate>Thu, 30 Apr 2009 15:59:04 -0500</pubDate>
        </item>
        
        <item>
            <title>Running VisualVM on a 32-bit Macbook Pro</title>
            <description><![CDATA[<p>If you want/need to run <a href="https://visualvm.dev.java.net/">VisualVM</a> on a <i>32-bit</i> Macbook Pro you'll need to do a couple of things. First, download and install Soy Latte, using <a href="http://landonf.bikemonkey.org/static/soylatte/">these instructions</a> - this gets you a Java 6 JDK/JRE on your 32-bit Macbook Pro. Second, download VisualVM and extract it wherever, e.g. /usr/local/visualvm. If you now try to run VisualVM you'll get the following error message:</p>

<pre class="prettyprint">
$ ./visualvm
./..//platform9/lib/nbexec: line 489: /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/bin/java: Bad CPU type in executable
</pre>

<p>Oops. After looking at the bin/visualvm script I noticed it is looking for an environment variable named "jdkhome." So the third step is to export an environment variable named 'jdkhome' that points to wherever you installed Soy Latte:

<pre class="prettyprint">
export jdkhome=/usr/local/soylatte16-i386-1.0.3
</pre>

<p>Now run the bin/visualvm script from the command line. Oh, almost forgot to mention that you should also have <a href="http://developer.apple.com/opensource/tools/X11.html">X11</a> installed, which it will be by default on Mac OS X Leopard. Now if all went well, you should have VisualVM up and running!</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/running_visualvm_on_a_32-bit_m.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/running_visualvm_on_a_32-bit_m.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Java</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Mac OS X</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">java</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">Mac OS X</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">macbook</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">visualvm</category>
            
            <pubDate>Wed, 01 Apr 2009 10:08:23 -0500</pubDate>
        </item>
        
        <item>
            <title>Missing aop &apos;target&apos; packages in Spring 3.0.0.M1 zip file</title>
            <description><![CDATA[<p>Today I was mucking around with the Spring 3.0.0.M1 source release I downloaded as a ZIP file. I wanted to simply get the sample PetClinic up and running and be able to load Spring as a project in IntelliJ. Note Spring now requires Java 6 to build, so if you're using an older 32-bit Macbook Pro you'll need to install JDK 6. I used <a href="http://landonf.bikemonkey.org/static/soylatte/">these instructions</a> generously provided by Landon Fuller to install Soy Latte, which is a Java 6 port for Mac OS X (Tiger and Leopard). So I went to run the "ant jar package" command (after first setting up <a href="http://ant.apache.org/ivy/">Ivy</a> since that is how Spring now manages dependencies) and everything went well until I got a compilation exception. There unfortunately wasn't any nice error message about why the compile failed.</p>

<p>So next I loaded up the Spring project in IntelliJ and tried to compile from there. Aha! It tells me that the org.springframework.aop.target package is missing as well as the org.springframework.aop.framework.autoproxy.target package, and of course all the classes in those packages were also missing. I was fairly sure I didn't accidentally delete those two packages in the source code, so I checked the spring-framework-3.0.0.M1.zip file to be sure. Sure enough those two 'target' packages are not present in the source code in the zip file. The resolution is to go grab the missing files from the Spring 3.0.0.M1 subversion <a href="https://src.springframework.org/svn/spring-framework/tags/spring-framework-3.0.0.M1/">repository</a> and put them in the correct place in the source tree. The better resolution is to do an export of the 3.0.0.M1 tag from the Subversion repo directly, rather than be lazy like I was and download the zip file.</p>

<p>I still am wondering why the 'target' packages were missing, however. My guess is that whatever build process builds the zip file for distribution excluded directories named 'target' since 'target' is a common output directory name in build systems like Ant and Maven and usually should be excluded since it contains generated artifacts. If that assumption is correct and <i>all</i> directories named 'target' were excluded, then unfortunately the two aop subpackages named 'target' got mistakenly excluded which caused a bit of head-scratching as to why Spring wouldn't compile.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/missing_aop_target_packages_in.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/missing_aop_target_packages_in.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Java</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">ivy</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">openjdk</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">soylatte</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">spring</category>
            
            <pubDate>Thu, 15 Jan 2009 18:06:22 -0500</pubDate>
        </item>
        
        <item>
            <title>Groovy + Spring = Groovier Spring</title>
            <description><![CDATA[<p>If you're into Groovy and Spring, check out my <a href="http://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=groovier+spring">two-part</a> series on <a href="http://www.ibm.com/developerworks/">IBM developerWorks</a> on using Groovy together with Spring's dynamic language support for potentially more flexible (and interesting) applications. In <a href="http://www.ibm.com/developerworks/java/library/j-groovierspring1.html">Part 1</a> I show how to easily integrate Groovy <i>scripts</i> (i.e. .groovy files containing one or more classes) into Spring-based applications. In <a href="http://www.ibm.com/developerworks/java/library/j-groovierspring2.html">Part 2</a> I show how to use the "refreshable beans" feature in Spring to automatically and transparently reload Spring beans implemented in Groovy from pretty much anywhere including a relational database, and why you might actually are to do something like that!</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/groovy_spring_groovier_spring.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/groovy_spring_groovier_spring.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Groovy</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Java</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">dynamic</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">groovy</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">java</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">spring</category>
            
            <pubDate>Tue, 06 Jan 2009 23:23:32 -0500</pubDate>
        </item>
        
        <item>
            <title>iPhone Bootcamp Summary</title>
            <description><![CDATA[ <p>So, after having actually written a blog entry covering <a href="/blogs/scott_leberknight/iphone_bootcamp_blogs.html">each day</a> of the <a href="http://www.bignerdranch.com/classes/iphone.shtml">iPhone bootcamp</a> at <a href="http://www.bignerdranch.com/">Big Nerd Ranch</a>, I thought a more broad summary would be in order. (That, and I'm sitting in the airport waiting for my flight this evening.) Anyway, the iPhone bootcamp was my second BNR class (I took the Cocoa bootcamp last April and wrote a summary blog about it <a href="/blogs/scott_leberknight/cocoa_bootcamp_at_big_nerd.html">here</a>.)</p>

<p>As with the Cocoa bootcamp, I had a great time and learned a ton about iPhone development. I met a lot of really cool and interesting people with a wide range of backgrounds and experiences. This seems to be a trend at BNR, that the people who attend are people who have a variety of knowledge and experience, and bring totally different perspectives to the class. The students who attend are also highly motivated people in general, which, when combined with excellent instruction and great lab coding exercises all week, makes for a great learning environment.</p>

<p>Another interesting thing that happens at BNR is that in this environment, you somehow don't burn out and can basically write code all day every day and many people keep at it into the night hours. I think this is due to the way the BNR classes combine short, targeted lecture with lots and lots and lots of hands-on coding. In addition, taking an afternoon hike through untouched nature really helps to refresh you and keep energy levels up. (Maybe if more companies, and the USA for that matter, encouraged this kind of thing people would actually be <i>more</i> productive rather than less.) And because of the diversity of the students, every meal combines good food with interesting conversation.</p>

<p>So, thanks to our instructors Joe and Brian for a great week of learning and to all the students for making it a great experience. Can't wait to take the OpenGL bootcamp sometime in the future.</p>]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/iphone_bootcamp_summary.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/iphone_bootcamp_summary.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Mac OS X</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">iPhone</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">apple</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">big</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">bootcamp</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">cocoa</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">iphone</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">nerd</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">ranch</category>
            
            <pubDate>Fri, 05 Dec 2008 17:08:29 -0500</pubDate>
        </item>
        
        <item>
            <title>iPhone Bootcamp Day 5</title>
            <description><![CDATA[<p>Today is Day 5 &mdash; the final day &mdash; of the iPhone bootcamp at <a href="http://www.bignerdranch.com/">Big Nerd Ranch</a>, taught by Joe Conway. The last day of Big Nerd Ranch bootcamps are half-days so you have breakfast, have class until lunch, have lunch, and then shuttle back to the airport. Unfortunately for me my flight isn't until 7pm so I have a lot of time to write this entry!</p>

<p>See <a href="/blogs/scott_leberknight/iphone_bootcamp_blogs.html">here</a> for a list of each day's blog entries.</p>

<h3>Preferences</h3>

<p>First up on this last day of iPhone bootcamp is preferences, which allow an app to keep user settings in a centralized location. While you can store user settings yourself using a custom UI, the easiest way is to use the iPhone's built-in Settings app. The Settings app is the central location where apps can store user settings. It is also where all the other common iPhone settings are, which is convenient.</p>

<p>You work with the <code>NSUserDefaults</code> object to store app settings based on the app's bundle ID, for example <code>com.acme.MyKillerApp</code>. You'll also want to ensure you provide "factory default" settings using  the <code>registerDefaults</code> method; these settings will be used if the user has not changed anything. <code>NSUserDefaults</code> is basically a dictionary of key-value pairs, and you obtain the standard user defaults using the <code>standardUserDefaults</code> method. From that point you can write user settings using methods like <code>setObject:forKey</code>, <code>setInteger:forKey</code>, and so on, and you can remove settings using <code>removeObjectForKey</code>. Similarly, you read settings using methods like <code>objectForKey</code>, <code>integerForKey</code>, and so forth.</p>

<p>As mentioned earlier, the Settings app is a uniform way of setting preferences for all apps. Users know where to look for setting preferences for apps there. In addition, managing the settings separately from your application also saves screen real estate, which is important since the screen isn't all that big. You define the settings for your application using the Settings Bundle. This is a standard Property List. You use special property keys, such as <code>PSToggleSwitchSpecifier</code>, to define the settings for your application. The Settings app uses the Settings bundle and property list to create the settings UI for your app. For example, if you define settings for a <code>PSToggleSwitchSpecifier</code>, a <code>PSTextFieldSpecifier</code>, and a <code>PSMultiValueSpecifier</code>, the user will see a toggle switch, a text field, and a slider when she goes to edit your app's settings.</p>

<p>For the lab exercise, we modified our Random Number app (from Day 4 during the Web Services section) to have user settings for how the random numbers are generated &mdash; for example minimum number and the range of numbers. It is quite easy to add user settings to your app in the iPhone using the Settings app and bundle.</p>

<h3>Instruments</h3>

<p>Joe briefly talked about using the Instruments app to do powerful debugging, for example to detect memory leaks in your app. He then demonstrated using the Leaks tool within Instruments to track a memory leak &mdash; which he had previously introduced intentionally &mdash; in the Tile Game app. Leaks was able to pinpoint the exact line of code where a leaked object (i.e. it was not released) was allocated. This is pretty cool.</p>

<p>Joe also showed what leaks look like when they come from C code versus Objective-C code. C-code allocation leaks (i.e. allocated using <code>malloc</code>) show up in Instruments as just 'General Block' and from what I gather are probably not that fun to track down the exact cause. Leaks in Objective-C code are easier, and as I just mentioned, Leaks can show you the exact line of code where a leaked object was allocated.</p>

<h3>Networking</h3>

<p>By this time, it is getting closer to lunch, and the end of the class. Sad, I know. Anyway, probably one of the hardest and broadest topics was saved for last, given that you could spend an entire course on nothing but network programming. Anyway, on the iPhone a key concept when doing network programming is "reachability." Reachability does <i>not</i> mean that a network resource is definitely available; rather it means the resource is "not impossible" to reach. Another important thing on the iPhone is figuring out what type of connection you have, for example EDGE or 3G or Wi-Fi. You might choose to do different things based on the type of connection.</p>

<p>With the SystemConfiguration framework you can determine if the outside world is reachable, again with the caveat the "reachable" means "not impossible to reach." When coding you work with "reachability references" and "reachability flags" which describe the type of connection, for example reachable, connection required, is wide-area network, and so on.</p>

<p>We then learned a bit about <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/NetServices/Introduction.html">Bonjour</a>, which is basically a zero-configuration network service discovery mechanism that works on all platforms, has implementations in many languages, and is easy to use. For example, Bonjour makes it ridiculously easy to find printers on a network, as opposed to the way you have to do it in other operating systems. You can use Bonjour on the iPhone to discover and resolve Bonjour services. You use <code>NSNetServices</code> and <code>NSNetServiceBrowser</code> to accomplish this, and you specify a delegate to receive notifications when services appear and disappear.</p>

<p>In addition to Bonjour, you can also send and receive data over the network as you would expect. To send and receive data you can either use a C-based Core Foundation interface or use a stream-based interface with <code>CFStream</code>. You register read and write callbacks with the main iPhone run loop, which calls your functions when network events occur.</p>

<p>Network programming is really hard, since there are so many things that can go wrong and you need to deal with many if not all of them. Joe recommended that before jumping right into hardcore networking, developers should become familiar with the concepts and recommended the <a href="http://beej.us/guide/bgnet/">Beej's guide to network programming</a> as a good primer. Given that I've really only done simple socket programming in higher-level APIs like Java's, and have not really done much of it, I'll need to check that out. And so this concludes this episode of iPhone bootcamp blog, since it is now time for lunch and, sadly, the course is over!</p>

<h3>Random Thoughts</h3>

<p>This week has been a really intensive introduction to iPhone programming. We've gone from a very simple app on Day 1 and covered all kinds of things like form-based UIs and text manipulation; Core Location; Core Graphics; view transitions and Core Animation; using the iPhone camera and accelerometer; retrieving web-based data; manipulating Address Book data; setting user preferences, and finally networking and debugging using Instruments. We've basically covered an entire book's worth of content and written about 10 iPhone applications ranging from simple to not-so-simple. If you are interested in programming the iPhone, I definitely recommend checking out the <a href="http://www.bignerdranch.com/classes/iphone.shtml">iPhone bootcamp</a> at <a href="http://www.bignerdranch.com/">Big Nerd Ranch</a>. Because the OpenGL stuff we did on the iPhone was so cool, I'm thinking my next course to take might be the <a href="http://www.bignerdranch.com/classes/opengl.shtml">OpenGL bootcamp</a> but that probably won't happen until next year sometime! With my new knowledge I plan to go home and try my hand at creating a snowflake or snowstorm application that my daughters can play with. If I actually get it working maybe I'll write something about it.</p>

 ]]></description>
            <link>http://www.nearinfinity.com/blogs/scott_leberknight/iphone_bootcamp_day_5.html</link>
            <guid>http://www.nearinfinity.com/blogs/scott_leberknight/iphone_bootcamp_day_5.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Mac OS X</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">iPhone</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">apple</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">big</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">bootcamp</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">cocoa</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">iphone</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">nerd</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">ranch</category>
            
            <pubDate>Fri, 05 Dec 2008 16:19:59 -0500</pubDate>
        </item>
        
    </channel>
</rss>
