Groovy and me, a long love story.

For many days I was trying to adapt some Plain old java test (POJT ?) on my groovy portage of Chromattic Framework (Object mapper to JCR).
This adaptation use the MOP, it’s a cool way to have a good chromattic integration.
But after quick test based on GroovyClassLoader, I have to port all the existing tests to my adaptation, but nothing work !
After several long hours of work in my code and original code, I have just found the real problem : Groovy !
When we say “groovy is dynamic, MOP is beautiful, MOP is cool” it’s not groovy but groovy in specific context.
Groovy called method have the same mechanism of method resolution of Java …
MOP feature seem available only if the call are made by groovy code …

Check this example :

class A {
 public Integer m() { return 3 }
 def invokeMethod(String m, Object p) { return 42 }
}

and Java unit test :

public class GoofyTestCase extends TestCase {
 public void testGroofy() throws Exception {
   assertEquals(42, new GroovyShell().evaluate("import org.chromattic.groovy.metamodel.B; new B().m()")); // true
   assertEquals((Object) 3, new B().m()); // true
 }
}

MOP is used only when the call are made in groovy script.
Do the Dynamic resolution be made by groovy or the groovy shell ?

Advertisements

Groovy setter generation

Today, I have to generate setter to annote it at the compilation time.

I’ve previously generate getter as following :

classNode.addMethod(
      GroovyUtils.getsetName(GroovyUtils.GetSet.GET, fieldNode.getName())
      , Modifier.PUBLIC
      , fieldNode.getType()
      , new Parameter[]{}
      , new ClassNode[]{}
      , new ReturnStatement(new FieldExpression(fieldNode))
    );

But If I try to generate setter :

    classNode.addMethod(
      GroovyUtils.getsetName(GroovyUtils.GetSet.SET, fieldNode.getName())
      , Modifier.PUBLIC
      , new ClassNode (Void.TYPE)
      , new Parameter[]{ new Parameter(fieldNode.getType(), "value") }
      , new ClassNode[]{}
      , new ExpressionStatement(new BinaryExpression(new PropertyExpression(new VariableExpression("this"), fieldNode.getName()), Token.newSymbol(Types.EQUAL, 0, 0), new VariableExpression("value")))
    );

and … nothing, no setter generated …

It’s time to check groovy sources code and I had found :

    public MethodNode getSetterMethod(String setterName) {
        for (Object o : getDeclaredMethods(setterName)) {
            MethodNode method = (MethodNode) o;
            if (setterName.equals(method.getName())
                    && ClassHelper.VOID_TYPE==method.getReturnType()
                    && method.getParameters().length == 1) {
                return method;
            }
        }
        ClassNode parent = getSuperClass();
        if (parent!=null) return parent.getSetterMethod(setterName);
        return null;
    }
    VOID_TYPE = new ClassNode(Void.TYPE)

… Groovy developers use a new instance of ClassNode and use == operator. they compare memory address (the instance) but not the value.

Just changing “new ClassNode (Void.TYPE)” by “ClassHelper.VOID_TYPE” resolve my problem.