Monday, July 5, 2010

Groovy tip: using methodMissing


There are 4 metaprogramming hooks in Groovy. These are:
  • invokeMehod: interceps method dispatch
  • methodMissing: intercepts fail method dispatch
  • get/setProperty: intercepts property access
  • propertyMissing: intercepts failed property access
Let's see how to use methodMissing to add dynamic finders (accessing data store) to a class.


If we run this code it will fail at runtime since we haven't defined the finder. In order to do this we need to add some metaprogramming.

All we're doing here is selecting the appropriate column in the database depending on the kind of finder invoked. This is working but it's not as efficient as it should be. What we can do is create a closure from that code and the cache it in the class. So now we have:

So instead of running through the whole methodMissing implementation every time the same finder method is called now we create a method dynamically and we add it to the class. This means that next time we call the same method it will be found (cached).

This is a trick that can be used to improve performance when using the metaprogramming hooks in Groovy.

Friday, July 2, 2010

Groovy tip: adding methods dynamically at runtime


From Groovy's perspective every class (including Java classes) have a meta-class associated to them. This meta-class can be used to obtain information on the underlying class or to add methods and properties on the fly. In other words, this is AOP made easy.

So let's say we have a Java class:

public class SuperHero {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

And I want to add a constructor that takes a name as a parameter. I also want to add a method:

SuperHero.metaClass.constructor = {String name -> new SuperHero(name:name)}
SuperHero.metaClass.fight = {"BAM!"}

println new SuperHero("Batman").name
println new SuperHero("Batman").fight()

The constructor is just a closure that sets the property for us.