Fork me on GitHub

LD.

Music, software, life… and stuff.

[ Twitter ] [ GitHub ] [ Linked In ]

Decorating Constructors with Groovy

I recently put out a new plugin for Grails that brings something like view models to Grails applications. An interesting feature of this plugin is that it supports direct object instantiation with implicit autowiring. You might think that Grails already support this, but it doesn’t. Currently, you can directly instantiate domain objects and get autowiring but you can’t write a constructor and use it here.

Groovy has had the ability to fiddle with a class’s constructors via EMC for a while.

class Thing {
    def i
    Thing() { i = 1 }
}

assert new Thing().i == 1
Thing.metaClass.constructor = { -> i = 2 }
assert new Thing().i == 2

Trying to augment existing constructors is a bit trickier though. Using the standard EMC API of setting a constructor property on the meta class, there is no way to access the constructor that is being replaced. To do this you have to dig a bit deeper.

For the view models plugin I needed to invoke the real constructor, then do some stuff to the new instance. My solution revolves around the registerInstanceMethod(groovy.lang.MetaMethod method) method of ExpandoMetaClass. After some digging through Groovy, I found that the technique above of setting a constructor property on the meta class boils down to just attaching an instance MetaMethod with a method name of <init> which is the name Groovy uses for constructors. So what we can do is subclass groovy.lang.MetaMethod to get our custom behaviour, which looks like this…

package grails.plugin.viewmodels.constructor;

import java.lang.InstantiationException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import groovy.lang.MetaMethod;
import org.codehaus.groovy.reflection.CachedClass;
import org.codehaus.groovy.reflection.ReflectionCache;

public class DecoratingMetaConstructor<T> extends MetaMethod {

    final private Constructor<T> constructor;
    final private ConstructionDecorator<T> decorator;

    public DecoratingMetaConstructor(Constructor<T> constructor, ConstructionDecorator<T> decorator) {
        super(decorator.getSignature(constructor));

        this.constructor = constructor;
        this.decorator = decorator;
    }

    public Constructor<T> getConstructor() {
        return constructor;
    }

    public int getModifiers() {
        return constructor.getModifiers();
    }

    public String getName() {
        return "<init>";
    }

    public Class<T> getReturnType() {
        return constructor.getDeclaringClass();
    }

    public CachedClass getDeclaringClass() {
        return ReflectionCache.getCachedClass(constructor.getDeclaringClass());
    }

    public Object invoke(Object object, Object[] arguments) {
        Object[] transformedArgs = decorator.transformArgs(arguments);
        T instance = instantiate(transformedArgs);
        decorator.decorate(instance, arguments, transformedArgs);
        return instance;
    }

    protected T instantiate(Object[] arguments) {
        try {
            return decorator.transformConstructor(constructor).newInstance(arguments);
        } catch (InstantiationException e) {
            throw new RuntimeException("Failed to invoke constructor " + constructor + " with args: " + arguments, e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Failed to invoke constructor " + constructor + " with args: " + arguments, e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("Failed to invoke constructor " + constructor + " with args: " + arguments, e);
        }
    }

}

A lot of that is just satisfying the MetaMethod methods. What’s of interest to us is that we take a constructor object, and a decorator which is an interface that we provide…

package grails.plugin.viewmodels.constructor;

import java.lang.reflect.Constructor;

public interface ConstructionDecorator<T> {

    public Object[] transformArgs(Object[] args);

    public void decorate(T instance, Object[] originalArgs, Object[] transformedArgs);

    public Class<?>[] getSignature(Constructor<T> constructor);

    public Constructor<T> transformConstructor(Constructor<T> constructor);
}

The decorator can supply a different set of args for the actual Constructor to those that were given to the invocation, supply a different Constructor instance to use at instantiation time and/or do something with the instance after it has been created.

We can use this mechanism to write a construction decorator that performs autowiring…

package grails.plugin.viewmodels.constructor;

import java.lang.reflect.Constructor;
import org.springframework.context.ApplicationContext;

public class AutowiringConstructionDecorator<T> extends ConstructionDecoratorSupport<T> {

    final private Autowirer autowirer;

    public AutowiringConstructionDecorator(ApplicationContext applicationContext) {
        this(new Autowirer(applicationContext));
    }

    public AutowiringConstructionDecorator(Autowirer autowirer) {
        this.autowirer = autowirer;
    }

    public void decorate(T instance, Object[] givenArgs, Object[] transformedArgs) {
        autowirer.autowire(instance);
    }

}

The Autowirer takes care of the actual autowiring details, which aren’t of much interest here (see the class here if you want).

So we can now take a class, and make all of it’s constructors implicitly perform autowiring by doing something like this…

def autowiringDecorator = new AutowiringConstructionDecorator(grailsApplication.mainContext)

for (constructor in MyThing.constructors) {
    MyThing.metaClass.registerInstanceMethod(new DecoratingMetaConstructor(constructor, autowiringDecorator))
}

Interestingly, I was able to use the same decoration mechanism to enable hot reloading support by obtaining the newest version of the constructor from the class loader in the Grails application that has the newest version of the class…

package grails.plugin.viewmodels.constructor;

import java.lang.reflect.Constructor;

class ReloadCapableConstructionDecorator<T> extends ConstructionDecoratorSupport<T> {

    private final ClassLoader classLoader;

    public ReloadCapableConstructionDecorator(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    public Constructor<T> transformConstructor(Constructor<T> constructor) {
        try {
            Class<T> originalClassVersion = constructor.getDeclaringClass();
            Class<T> newestClassVersion = (Class<T>)classLoader.loadClass(originalClassVersion.getName());

            return newestClassVersion.getConstructor(constructor.getParameterTypes());
        } catch (NoSuchMethodException e) {
            return constructor;
        } catch (ClassNotFoundException e) {
            return constructor;
        }
    }

}

The details of why this is needed isn’t worth going into now, what’s important is the fact that you could do some rather interesting stuff here.

If you find you have the need to decorate existing constructors as opposed to completely replacing them, it’s probably worth taking a look at what’s in the view-models plugin and either stealing it verbatim or adapting to your own purposes.

The relavant code and gory details can be found here.

Posted: Mar 4th, 2011 @ 3:54 pm

Tags: #software  #grails  #groovy  

Comments

Spock’s @AutoCleanup feature

You may have missed this little gem that was added to Spock in the 0.5 release…

import spock.lang

class InputStreamSpec extends Specification {

    @AutoCleanup
    def input = new FileInputStream("myfile.txt")

    def "some input stream tests"() {
        // …
    }

}

The spock.lang.AutoCleanup annotation works via Spock’s extension mechanism.

Let’s have a look at the documentation for @AutoCleanup (taken from the JavaDoc)…

spock.lang.AutoCleanup

Automatically cleans up the object stored in the annotated field or property at the end of its life time. More precisely, auto-cleanup of an object has the same effect as, and serves as a convenient replacement for, calling the object’s close method at the end of the spec’s cleanup method. @Shared objects are cleaned up at the end of the spec’s cleanupSpec method.

Customizing how cleanup is performed

By default, an object is cleaned up by invoking its parameterless close() method (which is assumed to exist); visibility and return type of this method are irrelevant. If some other method should be called instead, override the annotation’s value attribute:

@AutoCleanup("dispose") // invoke the object's "dispose" method

Cleaning up multiple objects

If multiple fields or properties are annotated with @AutoCleanup, their objects are cleaned up sequentially in reverse field/property declaration order, starting from the most derived class and walking up the inheritance chain.

Handling of exceptions during cleanup

If a cleanup operation fails with an exception, the exception is reported (just as if it had occurred in a cleanup or cleanupSpec method) and cleanup proceeds with the next annotated object. To prevent cleanup exceptions from being reported, override the annotation’s quiet attribute:

@AutoCleanup(quiet = true) // don't report exceptions

I find this extremely handy when testing some asynchronous code where I need an Executor as part of test fixture…

import spock.lang.*
import java.util.concurrent.Executors

class AsyncSpec extends Specification {

    @AutoCleanup("shutdown")
    def executor = Executors.newCachedThreadPool()

    def "some async bits"() {

    }

}

Over and above being very convenient, @AutoCleanup is great because it makes it easier to get your fixture setup out of your feature specifications and to also group fixture setup/teardown logic in one place.

Posted: Feb 6th, 2011 @ 12:22 pm

Tags: #software  #spock  

Comments

Disabling Grails plugin upgrade confirmation

Quick one…

If you want to permanently disable plugin version change confirmations (e.g. when another developer has changed a plugin version in BuildConfig.groovy), simply add this to your scripts/_Events.groovy:

def resolveDependenciesWasInteractive = false
eventResolveDependenciesStart = {
    resolveDependenciesWasInteractive = isInteractive
    isInteractive = false
}

eventResolveDependenciesEnd = {
    isInteractive = resolveDependenciesWasInteractive
}

Annoying messages be gone.

Posted: Jan 6th, 2011 @ 12:44 pm

Tags: #grails  #software  

Comments

Spock’s new matching support

Spock has an interesting new feature coming in 0.5 (but its available now in recent builds of 0.5-SNAPSHOT) integrating the Hamcrest matching library, which is an API for testing that something meets certain criteria. It’s always been possible to use Hamcrest with Spock but there is now a more convenient syntax. The expressiveness of Groovy generally makes Hamcrest not quite as generally useful as it would be when testing with plain Java, but it can still make your tests more concise and expressive when you have complex matching to do.

A classic example is for matching a value against another value within a certain error margin. Hamcrest comes with the closeTo matcher for this. This is how you might use it in a JUnit test…

import static org.hamcrest.Matchers.closeTo
import static org.hamcrest.MatcherAssert.assertThat

class HamcrestTests extends GroovyTestCase {
    def testIt() {
        assertThat(1.9d, closeTo(2, 0.5))
    }
}

This test will pass because the actual value 1.9d (the d tells groovy it’s a Double and not a BigDecimal) is within ± 0.5 of 2. The closeTo method is what’s known as a matcher factory (i.e. it returns an instance of org.hamcrest.Matcher)

Using Spock’s new convenient matcher syntax, we write the above as…

import spock.lang.Specification
import static org.hamcrest.Matchers.closeTo

class HamcrestSpec extends Specification {
    void "test closeTo"() {
        expect:
        1.9d closeTo(2, 0.5)
    }
}

Nice and concise isn’t it. The syntax is essentially…

«value» «org.hamcrest.Matcher»

There is also another variant…

import spock.lang.Specification
import static spock.util.matcher.MatcherSupport.that
import static org.hamcrest.Matchers.closeTo

class HamcrestSpec extends Specification {
    void "test closeTo"() {
        expect:
        that 1.9d, closeTo(2, 0.5)
    }
}

This syntax has the advantage that it can be combined with the assert keyword so can be used outside of the then/expect blocks (which the shorthand version can’t).

import spock.lang.Specification
import static spock.util.matcher.MatcherSupport.that
import static org.hamcrest.Matchers.closeTo

class HamcrestSpec extends Specification {
    void "test closeTo"() {
        setup:
        assert that(1.9d, closeTo(2, 0.5))
    }
}

Custom Matchers

As previously mentioned, a lot of the stock matchers that come with Hamcrest are not as useful in Groovy as they are in Java due to Groovy’s many convenience methods and expressive syntax. However, you can easily write your own Hamcrest matchers that are particular to your problem domain to make your tests more concise and maintainable.

Let’s use the example of a Grails application that lets user’s read books online. There is a very simple security model; users and books both belong to groupings and a user must belong to at least one grouping that a book belows to to be allowed to read it. Here is what our domain looks like…

class Book {
    String name
    static hasMany = [groupings: Grouping]
    static belongsTo = Grouping
}
class User {
    String name
    static hasMany = [groupings: Grouping]
    static belongsTo = Grouping
}
class Grouping {
    String name
    static hasMany = [books: Book, users: User]
}

We could write a custom matcher that checks if a given user can read a given book…

import spock.lang.*
import grails.plugin.spock.*
import org.hamcrest.BaseMatcher
import org.hamcrest.Description
import static org.hamcrest.Matchers.not

class ReadabilitySpec extends IntegrationSpec {
    def "test readability"() {
        when:
        def user = new User(name: "u1").save()
        def book1 = new Book(name: "b1").save()
        def book2 = new Book(name: "b1").save()

        def grouping1 = new Grouping(name: "g1")
        grouping1.addToUsers(user)
        grouping1.addToBooks(book1)
        grouping1.save()

        def grouping2 = new Grouping(name: "g2")
        grouping2.addToBooks(book2)
        grouping2.save()

        then:
        user canRead(book1)
        user not(canRead(book2))
    }

    def canRead(book) {
        [
            matches: { user -> user.groupings.any { it in book.groupings } },
            describeTo: { Description description -> description.appendText("user in one of groupings ${book.groupings*.name}") }
        ] as BaseMatcher
    }
}

Here we have implemented the canRead matcher factory as an instance method on our spec class. We are also using Groovy’s ability to convert maps into objects that either extend a given class or implement an interface. Here we create a map with the methods that we need to override from the org.hamcrest.BaseMatcher class then use as BaseMatcher to have Groovy create a dynamic subclass for us at runtime (note that this has nothing to do with Spock’s matching support, I am just using it here for conciseness).

We could factor out our custom matcher into a real class and perhaps move the factory method to a separate class as a static method, making it reusable across our project. You could quite easily build up a library of convenient matchers that express your problem domain.

Summary

Spock’s new Hamcrest support is yet another great feature that makes your testing easier and more concise. It’s another great tool to have in your bag of tricks when writing tests. For more info and examples, you can check out the test case in the Spock project that exercises this stuff.

Posted: Oct 10th, 2010 @ 4:24 pm

Tags: #software  #grails  #spock  

Comments

Archive · RSS · Theme by Autumn