Dynamically implement interface in Groovy using invokeMethod

dynamic, groovy, interface, reflection

Solution

You could use the Map coercion feature of Groovy to dynamically generate a Map that represents the given interface:

TestInterface getMapAsInterface() {
  def map = [:]

  TestInterface.class.methods.each() { method ->
    map."$method.name" = { Object[] args-> 
      println "Called method ${method.name} with ${args}" 
    }
  }    

  return map.asType(TestInterface.class)
}

Problem

Groovy offers some really neat language features for dealing with and implementing Java interfaces, but I seem kind of stuck. I want to dynamically implement an Interface on a Groovy class and intercept all method calls on that interface using GroovyInterceptable.invokeMethod. Here what I tried so far: ``` public interface TestInterface { public void doBla(); public String hello(String world); } import groovy.lang.GroovyInterceptable; class GormInterfaceDispatcher implements GroovyInterceptable { def invokeMethod(String name, args) { System.out.println ("Beginning $name with $args") def metaMethod = metaClass.getMetaMethod(name, args) def result = null if(!metaMethod) { // Do something cool here with the method call } else result = metaMethod.invoke(this, args) System.out.println ("Completed $name") return result } TestInterface getFromClosure() { // This works, but how do I get the method name from here? // I find that even more elegant than using invokeMethod return { Object[] args -> System.out.println "An unknown method called with $args" }.asType(TestInterface.class) } TestInterface getThisAsInterface() { // I'm using asType because I won't know the interfaces // This returns null return this.asType(TestInterface.class) } public static void main(String[] args) { def gid = new GormInterfaceDispatcher() TestInterface ti = gid.getFromClosure() assert ti != null ti.doBla() // Works TestInterface ti2 = gid.getThisAsInterface() assert ti2 != null // Assertion failed ti2.doBla() } } ``` Returning the Closure works fine, but I couldn't figure a way to find out the name of the method being called there. Trying to make a Proxy to the this reference itself (so that method calls will call invokeMethod) returns null.

Original source