Monday, 22 April 2013

When Grails Attacks

I've been pretty harsh on Grails before but I'm starting to appreciate some of its charms now. Of course I still think Play! 2.1 is even better but must admit there are fewer OMFGWTFBBQ?!?! moments with Groovy compared to Scala. That might just be me and my functional-programming newb-ness, or it might just be that while Groovy is a new front door on Java, Scala is a new top floor, roof and swimming pool out the back...

 Anyway.

Innocently trying to run some unit tests on an existing set of Grails controllers. Everybody else seems to be running them fine, but I get:

| Running 9 unit tests... 1 of 9
| Failure:  testThatAAABBDDD(BrokenAssTests)
|  java.lang.NullPointerException: Cannot set property 'method' on null object
 at BrokenAssTests.setup(BrokenAssTests.groovy:155)
| Running 9 unit tests... 2 of 9
| Failure:  testThatEEEFFGGG(BrokenAssTests)
|  java.lang.NullPointerException: Cannot set property 'method' on null object
 at BrokenAssTests.setup(BrokenAssTests.groovy:155)

The setup() method in question:
  @Before
  public void setup() {
    request.method = 'GET'
  }

 Same Groovy version, same Grails version, very similar Java version (1.7.0_11 vs 1.7.0_21, hardly a biggie), so what's going on?

I'm running Ubuntu 12.04, everyone else is on Macs (a story for another day).

A great deal of digging and Googling later, and here's what's going on:


  • Grails 2.0 introduced the TestFor annotation which automagically mixes in the ControllerUnitTestMixin  
  • As one of its many magic tricks, the ControllerUnitTestMixin adds mocked request and response objects into the test scope
  • This magic is performed in method bindGrailsWebRequest() which if you persue the documentation, has the JUnit 4 @Before annotation applied
  • The only ordering guarantee about @Before evaluation is "superclass comes before subclass"
  • But a mixin is NOT a superclass!
  • And so the order of @Before evaluation when using Grails' test mixins is essentially OS/JVM dependent
In my case, I was the unlucky "canary" on the "different" platform who encountered the bug. The "fix", such as it was, was manually calling the mixin method just-in-time in "our" setup() method:
  @Before
  public void setup() {
    if (!request) {
      bindGrailsWebRequest()  // Make sure request is visible - the ordering of @Befores is not guaranteed :-(
    }
    request.method = 'GET'
  }
I don't like it much, and hopefully the next version of Grails rectifies this, but for me it's just another one of those "too many layers of magic" problems that in my experience seems to afflict the Groovy world more than others.

Thursday, 18 April 2013

Backfillin'

One of my motivations for getting back into blogging after a considerable hiatus is the rise of the "cloud-based infrastructure" solutions which make it so much easier not just to host a software solution, but to develop one as well.

"The cloud" is a nebulous (see what I did there?) concept at best but strip away the management-pitched advertising and there are some amazing offerings out there for low- and no-cost.

As such I will be backfilling content from my old self-hosted Pebble blog onto this blog. I won't censor anything except for my ill-fated "setting up your own development server" series which, after a ludicrous number of instalments, is basically the best advertisement Cloudbees' Jenkins-As-A-Service could ever wish for!

Monday, 15 April 2013

Ubuntu Wubi: Here Be Dragons

After being handed a rather low-spec ThinkPad at my new gig, and attempting to get work done in a locked-down corporate Windows 7 installation, I gave up after two days. The main reason being Cygwin. It's cool and all, but it's not Linux. All the cool kids write install/run scripts that almost work in Cygwin, but not quite. Usually something to do with slashes and backslashes. The third time I had to go diving into someone else's shell script which would *just work* on Linux/Mac, I'd had enough.

Off to the Ubuntu site I trundled, and my eye was caught by the Wubi option - Install Ubuntu from "inside" Windows, thus minimising my unproductive "watch the progress meter" time.

So here is my advice for anyone who does more with their computer than light web-browsing or a spot of word-processing, strictly one app at a time:

Do NOT, under any circumstances, use Wubi to get Ubuntu onto your machine.

What you get after a Wubi Ubuntu installation is a disk image stored in your Windows directory, which you can choose from a boot loader, and it feels "just like Ubuntu". Because it is Ubuntu. Being run in a virtual disk, mounted from an NTFS partition. There are a lot of moving parts in that last sentence, and therein lies the problem.

Undoubtedly is a remarkable and clever achievement to be able to do all of the boot-record-jiggery and virtual-file-system-pokery from within a "hostile" operating system. But just because you can, doesn't mean you should.

My experience of the Ubuntu 12.10 OS running from a Wubi install was universally positive, until I started actually multitasking. Like this (each bullet being an "async task" as it were):

  • Open new Terminal -> Start pulling down new and large git updates
  • Open new Terminal tab ->Start pulling new and large SVN updates
  • Open new Terminal tab -> Kick off a grails application build and test
  • Open Chrome -> GRIND. BANG. LOCKUP
It seems the filesystem-intensive work being done in the terminal (particularly the Grails job that does a lot of temporary file twiddling) makes the virtual disk driver work hard, which in turn makes the NTFS filesystem driver do a lot of work. And between the two of them, they lock up THE ENTIRE MACHINE. Lights-on, nobody-home style. Press-and-hold-the-power-button style.

Then, after deciding you've had enough of your Wubi-based install, you have a very considerable number of fiery hoops to jump through to get your stuff out of its clutches and into a real disk mounted on a real filesystem.

So when (not if) you decide to liberate a corporate machine from Windows, take the hit and do the job properly - boot into the installer the way God/Shuttleworth intended, partition the disk correctly and enjoy.

Tuesday, 9 April 2013

Scala *is* Clean Code

Reading, learning, marvelling at Martin Odersky's creation thanks to his great book.

Everything I try (usually within the Play! 2.1 framework as that's just the cherry on top) just works, and as I learn more, I find 5 lines condenses to 3, condenses to 2, with no reduction in readability (as long as I name my variables properly).

My conclusion is that Scala is the closest thing I've seen to the physical embodiment of the Clean Code ideal. Huzzah!

Tuesday, 11 October 2011

Broken Toys

The keen might have noticed this site has been coming and going for the past fortnight :-(


The cause is yet to be determined - I attempted to log in on Monday and nothing was there - although I could SSH in to a different machine on my home network, the blog server was unpingable. I half-expected it to be smouldering from a particularly brutal DOS attack when I came home, but nothing so spectacular. It was just locked up.


I decided to take the opportunity and use this downtime to do some comprehensive upgrades I'd been wanting to perform for a while:

  • Move the server to Debian to match my other Debian/Ubuntu boxen
  • Upgrade my web platform to the latest-and-greatest Tomcat 7.0.22
  • Upgrade the blog software to Pebble 2.6.2 to get lots of fixes/improvements


Such big plans expose one to potential big failures. And I had a lot of them. Firstly, my wonderful, faithful little NetVista just simply didn't have the grunt to run anything much bigger than a "Hello World" webapp on the shiny new Tomcat/Debian stack - its 256Mb of RAM and puny 233MHz CPU had no chance against the might of a full JEE application like Pebble as well as running a beefcake OS like Debian (as opposed to the super-slender Puppy Linux it had before). So I moved the whole thing to a VM on a much gruntier Ubuntu Server I have. It remains to be seen what will happen to the little IBM - it's not adding much to the party at this point ...


So after migrating to the new hardware, and getting the new Pebble going, I had to bring in the performance improvements I blogged about a while ago, which still don't exist in the official Pebble codebase. (Note to self: must contribute those fixes back!). Initially it seemed all good - my YSlow score of 99 is mighty pleasing - but there was an elephant in the room.


Why the hell was it taking 8.5 seconds to serve up the home page?


Extensive (frustrating) investigation has shown that something added to Pebble since v2.4 has pretty badly borked the performance when hitting /. Fully-specified URLs are fine. I'm suspecting the new-in-2.5 SEO-friendly URL generator, but that's pure speculation. So until the bad interaction between Tomcat 7 and Pebble > 2.4 is sorted out, I'm stuck with icky URLs and no OAuth logins :-(

Tuesday, 4 October 2011

Make Sure You're Testing The Right Things

I'm going to come right out and say it. I love Unit Tests.


I love mocking the collaborators with Mockito (especially the annotation-driven mode). I love the small but oh-so-valuable mini-refactors that are sometimes necessary to make a class testable. And I love watching the code coverage march inexorably to the 100% asymptote.


What makes me very sad is seeing a sorry set of unit tests, and/or a poor development environment for testing. What do I mean?


  • If you're not mocking your collaborators, you're not unit testing. And if you're not unit testing, your code is Instant Legacy Code™. You cannot properly test any non-trivial class without needing to mock its dependencies.

  • Tests should be named in terms of expected behaviour. Method name testParseIntNullString() says nothing that couldn't be gleaned from looking at the test code itself. Method name shouldThrowFormatExceptionWhenParsingNullString() tells you the intention of both the code under test and the test itself. It's documentation that won't get out of sync with the code.

  • Use the facilities provided by your testing package. I'm a TestNG fan, but recent JUnit versions are pretty good too. I use TestNG's groups option in the @Test annotation to specify the style and/or scope of each test method. Another good one is the expected or expectedException annotation option that states what is going to be thrown. Much, much tidier than having try..catch blocks in test methods.

  • Code coverage is more than just a percentage. I use the eCobertura Cobertura plugin for Eclipse while I'm writing tests - to visually indicate which parts of the code I'm actually hitting. I've lost count of the number of times it's shown me an if I thought I had covered is still "red" due to a missing precondition.

Tuesday, 27 September 2011

Spring Roo Experiment, part 2

Making it perty

Roo does a great job of making a functional CRUD website, and that's great for an admin page. But public-facing websites, especially ones developed in 2011, need to look funky.


Enter Bootstrap, from the good people at Twitter. I'm not a Tweeter, but I have to extend maximum love and respect to these guys for turning out something to make things look so good, so easily.


Including the Bootstrap CSS in your webapp is like having the most web-2.0, rounded-cornered, missing-vowelled, fixie-riding front-end guy pairing with you, except he's actually completely finished the work, it works on all browsers and you don't have to listen to him talk about his iPhone all day :-)


Seriously though, Bootstrap does exactly what it says on the tin, with beautifully-clean, semantic markup, a wonderfully easy-to-use grid system and a contemporary, stylishly-minimal look.


I downloaded the Bootstrap CSS file and added it to my Spring Roo project by following these instructions - so now I can flip between the standard green Roo theme for my admin pages, and the super-funky Bootstrap theme for public pages. Lovely.