Showing posts with label groovy. Show all posts
Showing posts with label groovy. Show all posts

Wednesday, 11 February 2009

Case-insensitive ordering using HSQLDB

We've recently begun the process of testing our app on Postgres, and came across a problem where our 'order' statements were returning results in a different order to HSQLDB.

Postgres was ignoring the case of items, whereas HSQLDB was not - so if I were to order the strings "Al" and "AM", HSQLDB would show "AM" before "Al", but Postgres would show "Al" before "AM".

Given that the behaviour of Postgres (case-insensitive ordering) was the desired behaviour, we wanted to get HSQLDB to do the same. After a lot of searching any many dead ends, we found that you simply use ".ignoreCase()" after an order criteria:

List books = Book.withCriteria() {
ilike('authorName', "%${searchKey}%")
order('authorName', 'asc').ignoreCase()
maxResults(max)
}

Immutable Objects in Groovy

Anyone familiar with Joshua Bloch's book Effective Java will know about the importance of immutable objects. However, writing classes like that in Groovy always seemed to me to be problematic. You can declare the properties final but if the property type is itself mutable encapsulation is broken. Defining properties as private wasn't enough as Groovy lets you access them from anywhere regardless (I'm still not entirely clear why the language even supports it). A combination of final properties with overridden get methods where property types are mutable works but then you're writing almost as much code as you'd need to in Java and who knows what someone can get away with by using the .@ operator!

Google provided the solution this morning. It turns out there is an @Immutable annotation in Groovy that solves the problem in a very neat way even giving you an implementation of equals, hashCode and toString for free. Those methods tend to be pretty much templated in immutable classes anyway so getting effective implementations without writing any code makes a lot of sense and feels very 'Groovy'.

Tuesday, 6 January 2009

Groovy Truth and the instanceof Operator

I just stumbled across a little gotcha which would have failed compilation in Java, but in Groovy compiles but doesn't do what the developer intended.
    if (!obj instanceof SomeEnum) throw new IllegalArgumentException()
// do something with obj.name()
Clearly, the intention was to throw IllegalArgumentException if obj is not the correct type, but instead the code was throwing MissingMethodException from the access to obj.name().

The problem is missing braces. What Groovy is actually evaluating is
    if (false instanceof SomeEnum)
!obj evaluates to false as obj is not null. The correct code would be:
    if (!(obj instanceof SomeEnum)) throw new IllegalArgumentException()

Friday, 14 November 2008

Fun With Groovy Categories

Just a quick stupid trick I discovered. Commons Lang's StringUtils class works quite nicely as a category for String, e.g.
    use(StringUtils) {
println 'i can has cheezburger'.substringAfter('i can has ') // prints 'cheezburger'
}
Not only that but the JetGroovy plugin for IntelliJ IDEA will autocomplete all the new String methods inside the use block.

Wednesday, 29 October 2008

Joda DateTime Ranges

Recently I was attempting to create a Range representing the difference between two DateTime values so I could assert in a test that a date time value fell into that range. I was using Joda Time's DateTime class. The java.util.Date class is compatible with Groovy's ObjectRange becuase it's decorated with next and previous methods by the GDK. Joda's DateTime isn't, so I ended up doing this:
    DateTime start = new DateTime()
DateTime end = start.plusYears(1)
Range range = start.millis..end.millis
I could have created a custom Range implementation but I'd have lost the option of using the x..y notation and I'm a sucker for brevity. I figured Groovy has an IntRange class so there's probably a LongRange as well. As it turns out there isn't and what I ended up with is an ObjectRange.

Fundamentally this works, although I did find something worth bearing in mind. When it came to my assertion I tried to do this:
    static void assertInRange(Range expected, actual) {
if (!expected.contains(actual) {
fail("Expected value in range:<${expected}> but was:<${actual}>")
}
}
Simple enough, right? Except running the code caused the test to hang. Looking into the implementation of ObjectRange it became clear why. Groovy's Range interface extends java.util.List and that's where the contains method is specified. For compatibility with the List interface ObjectRange iterates over the values between its from and to properties using the next method I mentioned above. When from and to are Long instances, it turns out this iteration takes a while - on my 2.16GHz iMac the contains method takes over 4½ minutes on a 1 year range!

The Range interface also specifies a containsWithinBounds method and ObjectRange implements this by simply checking that the argument is >= from and <=to. Changing my assertion to use containsWithinBounds got rid of the long wait.

What ObjectRange is doing does make perfect sense. Given two arbitrary objects that implement Comparable and the next and previous methods it needs to implement contains in a way that conforms to the List interface. When you think about how the GDK implements next and previous on java.util.Date for example you can see that there may be possible values of a given class that fall inside a range but would never be part of the List generated by repeatedly using next on the range's from property. This isn't true of Long, of course, but ObjectRange is a general purpose class. The IntRange class has a much optimised version of contains and so could a theoretical LongRange implementation.

Anyway, getting back to the example. After changing contains to containsWithinBounds the code ran much faster, unfortunately it also threw java.lang.OutOfMemoryError: Java heap space. It turns out this is down to how GString handles the ObjectRange value I inserted into it. It spots that the object it's got implements List and uses InvokerHelper.toListString on it. This will attempt to create a String in the form "[0, 1, 2, 3...]". As you can imagine, building such a String is going to take some doing with over 31½ billion elements in the List, hence the heap space ran out.

A final working implementation of my assertion method is:
    static void assertInRange(Range expected, actual) {
if (!expected.containsWithinBounds(actual)) {
fail "Expected:<${expected.toString()}> but was:<${actual}>"
}
}
I think going for the custom Range implementation in the first place might have actually been the right choice.

Tuesday, 19 August 2008

When Groovy Property Access Attacks!

A quick best-practice hint...

Groovy's property access generally leads to terser code, however there's (at least) one time when using it is not a good idea; when you want to know what class an object is.

println x.class.name may work for most types of object, but what happens if x is, hmm let's say, a Map?

You probably won't be surprised to find the following code fails.

    def x = [:]
assert x.class == java.util.LinkedHashMap

Even more entertainingly, this code will throw NullPointerException

    def x = [:]
assert x.class.name == 'java.util.LinkedHashMap'

Thursday, 10 July 2008

Groovy operators

Max suggested I post something about this, so...

Groovy has some operators that vanilla Java doesn't. Here's a quick reference:

<=> (Spaceship)
Example:
a <=> b is equivalent to a.compareTo(b)

?: (Elvis)
Example:
x ?: y is equivalent to x != null ? x : y

=~ (Find)
Example:
Matcher m = "abc" =~ /a/

==~ (Match)
Example:
assert "abc" ==~ /\w+/ Note this is a full match not a partial.

~ (Create pattern)
Example:
~/abc/ is equivalent to new Pattern(/abc/)

*. (Spread)
Example:
a*.b is equivalent to a.collect { it.b }

.& (Method reference)
Example:
Closure c = a.&b gives you a reference to the method "b()" on object "a" that you can pass around as a Closure.

.@ (Property access)
Example:
def c = a.@b gives you the value of the property "b" on object "a" directly (i.e. without going through the getter). This can be useful on horrible classes like java.awt.Dimension where the type of a public property is different to the return type of its getter. Most other uses of it are probably best avoided.

?. (Null-safe dereference)
Example:
a?.b is equivalent to a == null ? null : a.b

as (Type coercion)
Example:
new Date() as String is equivalent to new Date().toString() which is a trivial example but you can do quite exciting type conversions by overriding asType.

is (Object identity)
Example:
a is b is equivalent to a == b in Java.

kthxbye.

Wednesday, 18 June 2008

String, GString type and equality

This might be very schoolboy blog for some of you - I still hope that it might be useful to avoid some bugs.

Some weeks back my pair and I were fixing a bug that finally boiled down to the fact that the contains() method on a List returned false if the list contained the GString counterpart of the same literal.

Having played a bit I learned a couple of things about GStrings. Please find some bullet points and the code snippet bellow.

Type:
1. def var1 = "this is a String instead of a GString even if it is surrounded by double quotes - can has no dollar sign"
2. def var2 = "this is a GString because it contains a dollar sign - $var1"
3. String var3 = "this is a string because it was defined as a String"
4. String var4 = "$var3 - this is still a string because it was defined as a String"

Equality
1. a String and a GString can be ==
2. a String and a GString are NEVER equals()
3. as a consequence a list containing a literal will not return true if the type (GString/String) does not match


class WhereIsYourDummyTests extends GroovyTestCase {
def e = "y"
def dummy = "dumm$e"

void assertTypeIsStringForAFixGString() {
assert e instanceof java.lang.String
assert dummy instanceof groovy.lang.GString
}

void testEqualsNotEquals() {
assert "dummy" == dummy
assert dummy == "dummy"

// WATCH OUT HERE
assertFalse("dummy".equals(dummy))
assertFalse(dummy.equals("dummy"))
}

void testContainsDoesntContain() {
assert ['dummy'].contains("dummy")
assert ["dummy"].contains('dummy')
assert [dummy].contains(dummy)

// THIS IS TRICKY:
assert ![dummy].contains("dummy")
assert ![dummy].contains('dummy')
assert !["dummy"].contains(dummy)
assert !['dummy'].contains(dummy)

assert [dummy.toString()].contains("dummy")
assert [dummy.toString()].contains('dummy')
}

void testContainsIfVariablesAreStringInsteadOfDef() {
String e = "y" // String instead of def
String dummy = "dumm$e" // String instead of def

assert ['dummy'].contains("dummy")
assert ["dummy"].contains('dummy')
assert [dummy].contains(dummy)

assert [dummy].contains("dummy")
assert [dummy].contains('dummy')
assert ["dummy"].contains(dummy)
assert ['dummy'].contains(dummy)

assert [dummy.toString()].contains("dummy")
assert [dummy.toString()].contains('dummy')
}
}

Thursday, 15 May 2008

Fear & Loathing in the MetaClassRegistry

On your testing travels you may, on occasion, mock methods out on certain classes using the old metaClass trick:
MyLovelyClass.metaClass.'static'.myLovelyMethod = { //crazy stuff here }

Now the fun with this approach is that when/how/where/how long/huh? feeling you get when you realize that other tests in the the suite start failing - dreaded test bleed (insert dramatic soundclip here).

Thanks to the Groovy method reference operation (&) and the MetaClassRegistry all can be made well, without having to resort to sticking all the initial method references in a map (or similar) and trying to stuff it all back on the original class in your tearDown():
void tearDown() {
def remove = GroovySystem.metaClassRegistry.&removeMetaClass
remove MyLovelyClass
}

Hmmm. I feel a bit lightheaded. Maybe you should drive.

Wednesday, 23 April 2008