Monday, December 29, 2008

XmlParser trim whitespace by default

I just found out that groovy.util.XmlParser trims whitespace by default. When parsing XML files with text nodes that contain trailing whitespace, for example, whitespace is removed in the Node returned by the parser.

def parser = new XmlParser()
def doc = parser.parseText("ABC ")
assert == "ABC" // Not "ABC "!

To preserve whitespace, set the trimWhitespace property to false:

def parser = new XmlParser(trimWhitespace: false)
def doc = parser.parseText("ABC ")
assert == "ABC "

Monday, December 22, 2008

View the source of compiled GSP

While grails is running in development mode, you can view the source of the compiled GSP by appending showSource to the URL. E.g.


This trick is mentioned in and was requested as an improvement in JIRA

I wonder how many more of these tricks are in grails.

Wednesday, November 19, 2008

Getting uptime in Windows

In Linux environment, we can get the uptime of the workstation with the command uptime. But how do you find out how long your Windows has been running?

I found out recently that you can do this:
net stats server | find "Statistics since"

It doesn't tell you exactly how long your PC has been up and running, but it does tell you the time your Windows started.

Thursday, July 24, 2008

Adding jar to classpath at run time

Whenever I want to test some groovy ideas, I use groovyConsole. However, I don't want to copy the dependent jar files into my $HOME/.groovy/lib, and as of groovy 1.5.6, it is still not possible to add -classpath to the command line of groovyConsole.bat.

I found a solution on the web. Just add this line into the start of the code:

this.getClass().classLoader.rootLoader.addURL(new File("file.jar").toURL())

Better still, use a list:

[ "file1.jar", "file2.jar" ].each {
this.getClass().classLoader.rootLoader.addURL(new File(it).toURL())

Monday, May 12, 2008

SQL Keywords As Column Names

Once in a while, I got caught by my own mistake by using SQL keywords as column names. For example, this looks pretty harmless (but it fails in GORM):

class Person {
String userName
String password
String group

There are 2 problems:

  1. password is a keyword in MySQL.

  2. group is an SQL keyword.

Although it usually doesn't take me too long to realize my mistake, it is a nuisance that I'd rather live without. There is a more systematic way to detect such problem.

Wednesday, March 19, 2008

Create recursive markup with MarkupBuilder

I just found a way use Groovy's MarkupBuilder to build an XML file with nested elements. Assuming I have a container with a collection of X objects and a Y object. The XML output of the container can be generated as follows:

import groovy.xml.*

class X {
private int id
private String name

def toXML = { builder ->
builder.x(id: id, name)

class Y {
private Date date = new Date()
def toXML = { builder ->
final sdf = new java.text.SimpleDateFormat("yyyyMMdd'T'HH:mm:ssZ")
builder.y(date: sdf.format(date))

def w = new StringWriter()
def xml = new MarkupBuilder(w)
xml.doubleQuotes = true
def xa = [ new X(id: 1, name: "x-name"), new X(id: 2, name: 'x-name2') ]
def yObj = new Y()
xml.root() {
agent(id: 1, name: 'agent1', "X")
xa.each { xo ->

The variable w is equivalent to:

<agent id="1" name="agent1">X</agent>
<x id="1">x-name</x>
<x id="2">x-name2</x>
<y date="20080318T23:56:54+0800" />

Notice that to get the builder to output double quotes for attributes, I set the doubleQuotes property to true.