Wednesday, April 29, 2009

Enabling the "Accept" header for Grails/REST

I've been trying to implement a RESTful web service using Grails, following along a number of articles on the web for examples (Scott Davis has a particularly good one here: RESTful Grails). To get back XML from a Grails app that will be serving up both HTML and XML, I was setting the HTTP "Accept" header, then using content negotiation in my controller classes to determine what to send back to the client. For some reason, though, my app kept spitting back HTML even when I was specifically requesting XML.

Well, it turns out that, according to this Jira post, as of Grails 1.1, using the Accept header is disabled by default. To enable it, open up the Grails app's Config.groovy file (grails-app/conf/Config.groovy), and set "grails.mime.use.accept.header" to true.

Once I got that figured out, everything is running really smoothly.

Tuesday, April 28, 2009

Playing a nicer beep in Gnome terminal under Ubuntu

With all the tab-completion and such that I do at the command line, sometimes that system beep can get really annoying. I like to have audio feedback when I'm working, so I didn't want to disable the beep completely, but I did want something that wasn't quite so harsh. I searched around for a while in the preferences to see if I could change things to play a nicer sound file instead of the speaker's beep, but it doesn't look like that's available as an option. Searching the web, I found this post at tjworld.net, which got my system playing the sound file I wanted: XandGnomeSystemBeepWithAudioFile. (Note: there's a misspelling for the xkbevd config file name in that post; it's actually "xkbevd.cf".)

While that finally got a sound file playing instead of the beep in other apps, in the Gnome terminal, it played both the sound file *and* the system beep . . . even more annoying :). In the end, here's what I had to do to get *only* the sound file playing as the beep in the Terminal:

First, in the System->Preferences->Sound preference setter, go to the System Beep tab, and de-select "Enable System Beep".

Next, in the Gnome terminal Edit->Profiles menu, select the profile you're using, then on the Edit->General tab make sure "Terminal bell" is selected.

So, you have to *disable* the system beep in the global settings, then *enable* it in the terminal settings.

Wednesday, April 1, 2009

Accessing the Maven runtime classpath in a Groovy script

Lately, I've been involved in converting a good portion of our source tree that's currently built with Ant over to building with Maven. We have a number of Groovy scripts that we use throughout our build, and I've had great success with the GMaven plugin to get things working. I ran into one snag, though, when I was trying to run one of our Groovy scripts that generates Textile wiki markup via a custom Javadoc doclet.

To get the doclet to run, I needed to supply the path/classpath where it could be found, and since the doclet is built during the project's compile phase, I needed access to the Maven runtime classpath to get the documentation built (admittedly, it shouldn't be part of the "project", but if it were, instead, an outside dependency, I'd still need access to the Maven compile classpath, so the problem is pretty much the same). The Maven AntRun plugin provides a nice reference to that classpath via the "maven.runtime.classpath" property that can be accessed in the Maven Ant targets, so I was hoping that GMaven would provide the same sort of thing, especially since they give good access to an AntBuilder automatically.

At this point, though, they don't, and I really didn't want to resort to embedding Ant in our Maven build just to run a Groovy script (for a number of reasons). After a good amount of experimentation and searching, I found this GMaven Jira entry that gives a little bit of guidance for how a GMaven Mojo might build those same kind of classpath references. It didn't really address how to get those classpaths in an executed script, though, but Groovy is Groovy, so I figured it could be done :). Experimenting with what's laid out there and digging into the Ant API docs, here's a what I came up with:

First, of course, you need to get GMaven to run during your build. The GMaven documentation is great for showing how to edit your POM to call a Groovy script during the build. Next, in the Groovy script you want to run, you need to import org.apache.tools.ant.types.Path, and instantiate a new Path object (before you want to reference the path, naturally). When you make a new Path object, you need to give it a reference to the Ant Project to which it belongs, and, as I mentioned, GMaven gives you reference to an AntBuilder (via the "ant" default variable) where you can get that project. The code so far might look like this:

import org.apache.tools.ant.types.Path

Path runtimePath = new Path(ant.antProject)


Once you have that Path object, you need to tell it what its path should look like. Since we're trying to set the runtime classpath Maven builds, we need to find out what JAR files and compiled classes are in Maven's runtime classpath. Fortunately, GMaven also gives us access to a MavenProject object by default, referenced by the default variable "project" in the script. We can build up our path, then, by joining the different pieces of the MavenProject's runtimeClasspathElements and setting that to our Path's path:

runtimePath.path = project.runtimeClasspathElements.join(File.pathSeparator)


Finally, in order to reference that path by name in our script where we need it, we have to add a reference to it in our Ant Project object:

ant.antProject.addReference('runtime.classpath',runtimePath)


The final code for building the runtime classpath looks like this:

import org.apache.tools.ant.types.Path

Path runtimePath = new Path(ant.antProject)
runtimePath.path = project.runtimeClasspathElements.join(File.pathSeparator)
ant.antProject.addReference('runtime.classpath',runtimePath)


Once we have that defined, we can reference it in the script just like we would any other Ant reference. For example, in the project I'm working on, I need to supply a path reference to the Ant Javadoc task. Since I named the path above "runtime.classpath", I set up my Javadoc task call in the Groovy script like this:

ant.javadoc(... docletpathref: 'runtime.classpath' ...) {
... more Groovy code to execute ...
}


While it would definitely be easier if GMaven provided these classpaths out of the box, it's actually not that hard to build them up in the script when you need them. By the way, you can do the same thing with the Maven compile classpath: instead of referencing "project.runtimeClasspathElements" when building the path, you use "project.compileClasspathElements". If you need the plugin classpath, the process is a little more complex, but if you get what's going on above, then you can probably follow the example in the GMaven Jira post to build the plugin classpath.