Tuesday, August 26, 2008

Having trouble installing the Quartz plugin? Read on...

For those of you who don't follow the grails-users list, I thought I'd post a quick solution to solving an odd-looking compile error when installing the Quartz plugin into a Grails application that also uses the JSecurity plugin.
The compile error you will see is:
GrailsJobFactory.java:75: cannot find symbol
symbol  : constructor JobExecutionException(java.lang.String,java.lang.Exception)
location: class org.quartz.JobExecutionException
    throw new JobExecutionException(e.getMessage(), e);
It's caused by a library clash between the two plugins as JSecurity also ships with quartz.jar. Luckily (according to Les from the JSecurity project), JSecurity doesn't actually rely on that jar so you can delete it from plugins/jsecurity-x.x/lib which will solve the compile issue.

Monday, August 18, 2008

Grafton Hillclimb

I attended the Grafton Sporting Car Club's hillclimb on the weekend for the first time. It was loads of fun, and the first time I had my car out on a track. I managed to get under 60 seconds which was my goal for the day but hope to be a lot closer to the Evo's next time. I headed down with some top blokes from EvoOz and made a weekend of it. I can't wait to go back with improved suspension and tires, I just need to develop the business case in order to get it past the Minister for Finance. I think I'll try the improved safety angle... You can see how tight and technical the track is below.

View Larger Map
This is a shot taken by Nigel from Unique Images. Thanks a lot Nigel!
Photobucket - Video and Image Hosting

I feature at around 2:30 and 7:00 in the below video - great camera work/commentary by 'Pres' from EvoOz.

Tuesday, August 5, 2008

Jasper Reports Grails Plugin - sub-reports

Here's something that tripped me up when developing my first JasperReport containing a sub-report for use with the JasperReport grails plugin. In order for the sub-report to resolve correctly you need to add a parameter to your parent report called SUBREPORT_DIR. This is then set by the JR plugin, and makes everything work as expected. When specifying the sub-report location, set it to
$P{SUBREPORT_DIR}  + "mysubreport.jasper"
(assuming your subreport is in the same directory as the parent report and called mysubreport.jasper) Don't forget to give the parameter a default value of empty string so that it still works when previewing in iReport. You also need to remember that the plugin runs the compiled versions (*.jasper not *.jrxml) so you need to compile the reports with iReport before running the application.

Monday, August 4, 2008

Jasper Reports Grails Plugin Gotcha

Thought I'd blog this quickly: If you're using iReport to develop reports for use with the Jasper Reports grails plugin, make sure you download the version that matches the version of Jasper that the plugin uses (currently 2.0.5). Otherwise you get terribly unhelpful exceptions like:
java.lang.NullPointerException
 at net.sf.jasperreports.engine.JRPropertiesMap.readObject(JRPropertiesMap.java:185)

Thursday, July 24, 2008

Functional Test Driven Development with Grails and WebTest

EDIT: Most of this functionality is now available in 0.6 Alpha: This is not a new idea by any stretch of the imagination, however, I thought I'd post about how I've been doing it recently. The Grails WebTest plugin comes with a script which will start your application, run all your test, and shut down the application. This is great for checking your code before checking in or for running on your continuous integration server. However, if you would like to use a WebTest to drive out some functionality it is far too slow. To get around this I have been using a custom script and parent class for my WebTests. The script is basically a copy of RunWebtest.groovy supplied by plugin with the start/stop application code removed. It also has a small section of code to parse a class patttern and method pattern as arguments. It needs to be placed in the plugins/webtest-0.5/scripts directory of your application so that it can access the required WebTest configuration and resources. This allows for a command such as: grails run-webtest-only MyDomain edit which will run all test methods containing the word edit but only those methods found in classes with a name containing the word MyDomain. In order for this to work, you also need to modify call-webtest.xml, found in the plugins/webtest-0.5/scripts directory. Add clonevm="true" to the java tag at line 10. This is required so that the system properties set in RunWebtestOnly.groovy are passed through the java process that actually runs the tests. This allows you to pick out one or two key tests that you are working on and run them quickly and repeatedly without restarting the application. It also has a nice side effect of forcing you to write robust, repeatable tests as you will be running the test multiple times against the same database without refreshing the data. The second part of the solution is the custom parent class for the WebTests. By default, the WebTest plugin requires you to add a suite method to your WebTest to specify the order in which to run the test cases contained within it. This is very useful if there are dependencies between the cases and testA must run before testB for example. To me, this is a bit of a smell that your tests are too fragile. If testA must run before testB in order to set up some state, refactor the code that creates that state into a method and re-use it in testB with unique values so that you can run testB regardless of database state. Of course there are always exceptions, especially when it comes to keeping test execution time to a minimum, and in reality it may be better to set up common data once and re-use it in several tests. My opinion above is given with a "in an ideal world" disclaimer. Apologies, I'm getting side tracked! What my custom parent class does is model JUnit in that it automatically builds a suite from all methods beginning in 'test'. It also applies the class and method filters you gave to the run-webtest-only script which are passed through from Gant via system properties. Now with the help of the WebTestRecorder firefox plugin I can start to drive out a new page, menu item or behaviour. I find this method very useful in forcing a methodical, logical approach to developing new code and also makes it very easy to 'do the simplest thing' as you drive all code changes from the front end from the users point of view. As usual, there are always exceptions, and you should always refactor and add any additional integration or unit tests required to cover exception handling or complicated logic that you cannot drive out from a WebTest. My internal dialog normally goes something like this: "Right, so I need to add a new field to X. First, I need to record browsing to the list screen and creating a test X" click, click, click, cut and paste "Ok, next I want to be able to enter a value for field Y when creating an X." setInputField(name:'Y',value:'someValueForY') clickButton('Save') "This should now fail..." run-webtest-only XTests editY "Excellent, I can now go and modify the GSP to add the input field" and so on and so on... Make sure you you only do enough at each stage to make the test pass, in the above example, I could go off and add the field to the domain class and update the controller if necessary, however all the test is making me do so far is add an input field to the GSP. Once the test is checking that the value of Y is persisted and displayed on the show or list screen, then I can go and make those changes. It can be hard to stay disciplined but hopefully you have access to a pair and can keep each other honest. I openly admit to cutting corners when working on my own. It's not my fault, Grails makes my actual coding so fast, the tests just slow me down!! ;)

Wednesday, July 23, 2008

Audi helps you time the lights!

The latest technology to come out of Audi shows the driver the perfect speed to drive in order to avoid red lights at upcoming traffic lights! Admittedly, the traffic lights in a German town were modified for the technology to work, but it's still an awesome idea! Source: http://blogs.cars.com/kickingtires/2008/07/audi-takes-on-s.html

Sunday, July 20, 2008